- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
public static Rectangle2D fit(final Rectangle2D in, final Rectangle2D out) {
final Rectangle2D.Double fit = new Rectangle2D.Double();
if (in.getWidth() > in.getHeight()) {
fit.width = out.getWidth();
fit.height = (out.getHeight() * in.getHeight()) / in.getWidth();
fit.x = out.getX();
fit.y = out.getY() + ((out.getHeight() - fit.height) / 2);
} else {
fit.width = (out.getWidth() * in.getWidth()) / in.getHeight();
fit.height = out.getHeight();
fit.x = out.getX() + ((out.getWidth() - fit.width) / 2);
fit.y = out.getY();
}
// if ((in.getWidth() / in.getHeight()) != (fit.width / fit.height)) {
// throw new RuntimeException();
// }
// if (!fit.contains(fit)) {
// throw new RuntimeException();
// }
return fit;
}
# 17: // if (!out.contains(fit)) {
в жабе есть assert который никогда не работает.
Почему?
Потому и не использую.
То же самое в современных Си-компиляторах. #ifdef нужен был в доисторические времена, когда компиляторы были тупыми.
Если это приложение - вы уж или используйте Guava, или нет. Если это библиотека - добавляйте Guava как жёсткую зависимость, да и всё.
Кстати, конкретно эта задача решается вообще просто:
Не хотите делать для каждого класса подкласс - сделайте статический метод, который будет возвращать реализацию интерфейса через duck typing и reflection.
Поможет только наличие стандартных функций (и проектирование библиотек с использованием таких функций), или, на крайняк, имплиситы из скалы.
Та блядь, написал ответ - а сайт с эксептом свалился.
Процессоры compile-time аннотаций тоже не имеют отношения к препроцессору, ибо работают на уровне деклараций, а не токенов, это совершенно другой уровень. Например, нельзя изменить синтаксис языка.
насколько я помню, в сишке препроцессор работает на уровне исходного текста по принципу "найти и заменить", еще до лексического разбора - так что еще токенов там нет
препроцессор для макроса со скобками должен проверить, что это действительно макрос со скобками (отличить max(... от _max(... и от (max)(... ), проверить число аргументов, вызвать макросы в новом тексте и т.д.
так что простейший разбор на токены там есть
Это важно?
Понимаешь разницей между обработкой абстрактного сферического текста ПЕРЕД вызовом компилятора и обработкой языковой структуры, СОЗДАННОЙ компилятором?
Аннотации сами по себе - нет. Это просто заметки, пристегнутые к соответствующим точкам кода.
А вот annotation processor, подключенный к компилятору, уже может сделать все что угодно - и генерацию, и дегенерацию, и перехуяцию.
Ну и в рантайме можно почитать эти аннотации, и воспользоваться ими в своих грязных целях.
это можно сделать аннотациями?
Если честно - а хрен бы знал. Сейчас покопался в доках - получается, что annotation processor'ы сами по себе не были предназначены для модификации кода, а должны генерить что-то новое - конфиги, новые классы, которые потом будут загружены и.т.п...
Но, как показали некоторые найденные примеры (из-за которых я по глупости и поверил во всесильность процессоров), если перейти на темную сторону заюзав внутреннее API javac'а - com.sun.tools.javac.tree, то можно перепиливать даже код внутри методов.
http://www.docjar.com/docs/api/com/sun/tools/javac/tree/JCTree$JCClassDecl.html
Скорее всего будет достаточно добавить нужный интерфейс в список implementing. Но я совершенно в этом не уверен ;(
Хотел на OpenJDK потестить чорную магию с API javac'а, и обломался т.к. там нет нужных интерфейсов...
можно модифицировать байт-код и сделать новый класс, и загрузить его новым класслоадером, тем же asm
Зачем? Тут вроде речь шла о compile-time преобразованиях...
Кэп: подготавливать сорцы к встрече с создателем конпейлятором. Например, опцианально подключать поддержку библиотек, чтобы не тянуть ворох ненужных зависимостей.
> стоит ли это делать таким образом?
В 98% случаев нет. Толко рантайм и куча модулей, только хардкор.