После 16 лет каждый программист мечтает о большой любви. Дни становятся пустыми и длинными, а ночи беспокойными. Когда же придет Она? Неужели я всю жизнь буду вынужден провести в одиночестве за этим дурацким компьютером?! И конечно он мечтает о том, как встретит Ее, как пригласит на свидание, как они будут гулять по темным улицам или в заброшенном старинном парке, он будет Eе держать за руку, и … (о нет как же это мучительно сладко представлять!) они поцелуются. А так как он программист, то мечты обычно он выражает достаточно своеобразно, на любимом языке программирования.
Герой нашего нашего рассказа — это начинающий программист, который пытается разобраться с аннотациями (java.lang.annotation.*), средством языка Java, позволяющим вносить в код дополнительные метки (более точно сказать модификаторы). После их определения во время исполнения программы можно выбрать для вызова тот или иной конкретный метод.
Вот, представляет он, хочу пойти я на свидание, как же мне себя вести с девушкой? Как я почувствую что я влюбился? Как же мне это узнать? Наверно, размышляет он, я могу влюбиться только тогда, когда мы поцелуемся в первый раз...
package programmer;
public interface Date { // свидание
public void firstSight();
public void walkUnderMoon();
public void takeHerHand();
@FallInLove
public void firstKiss();
}
Ну хорошо, размышляет он дальше, после поцелуя, влюбится можно в любую девушку! Так и представляю себе как она, распустив свои светлые волосы, медленно приближается ко мне губами.... Мммм.. Блондинка! Да, пожалуй в блондику я влюблюсь немного раньше... Первая молния проскочет между нами, когда я возьму ее за руку...
package programmer;
public class BlondeDate implements Date { // свидание с блондинкой
public void walkUnderMoon() {}
@FallInLove
public void takeHerHand() {}
public void firstKiss() {}
public void firstSight() {}
}
А вот здорово было бы увидеть
Анжелину Джоли, мечтает он. Конечно у нее есть Бред Пит, и вообще у нас в Бердянске ее, конечно, не встретишь... Ну да ладно, выхожу из дома на тупике Рудневой, открываю кулек с семками, поднимаю глаза и вдруг … Она! Светлые волосы подсвечивает заходящее солнце, их глаза встречаются, и он чувствует что сердце сейчас просто выпрыгнет из груди.
Тут внимательный почитатель таланта и красоты Анжелины возмутится. Позвольте, какая же Джоли блондинка? Она шатенка! Давай-ка ты программист, ври да не завирайся! Уважаемый читатель! Наш юный друг просто восхищенный подросток, и в сокровенных мечтах Анжелина видится ему именно шикарной блондинкой. Не будем ему мешать.
package programmer;
public class AngelinaJolieDate extends BlondeDate {
@FallInLove
public void firstSight() {}
public void walkUnderMoon() {}
}
Тут наш замечтавшийся юный друг засыпает с улыбкой на лице, а когда просыпается решат вспомнить все и проверить правильно он понял применимость аннотаций. Для начала он посмотрев документацию пишет класс аннотации. Он не забывает добавить @
Retention(
RetentionPolicy.RUNTIME), которая показывает, что аннотации должны существовать в классах во время работы программы, а также применимость аннотации к методу @
Target(
ElementType.METHOD).
package programmer;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface FallInLove { //j
}
И решается все проверить в месте:
package programmer;
import java.lang.reflect.Method;
public class SweetDreams {
private static Date date_02_07 = new AngelinaJolieDate();
public static void main(String[] args) throws Exception {
System.out.println("My secret dream");
// проверить реализуют ли методы класса, суперкласса
// и интерфейса созданною нами аннотацию
Class<?> date = date_02_07.getClass();
while (!date.getName().equals("java.lang.Object")) {
dream(date);
for (Class<?> i : date.getInterfaces()) {
dream(i);
}
date = date.getSuperclass();
}
}
public static void dream(Class<?> about) throws Exception {
System.out.println("I dream about: " + about.getName());
for (Method m : about.getMethods()) {
// проверка использует ли метод аннотацию
if (m.getAnnotation(FallInLove.class) != null) {
System.out.println(
"I can fall in love if " + m.getName());
m.invoke(date_02_07,null);
}
}
}
}
Вывод его несколько обескураживает.
My secret dream
I dream about: programmer.AngelinaJolieDate
I can fall in love if firstSight
I can fall in love if takeHerHand
I dream about: programmer.BlondeDate
I can fall in love if takeHerHand
I dream about: programmer.Date
I can fall in love if firstKiss
Я сразу влюблюсь в Анжелину, если я встечусь с ней глазами. Откуда здесь взялся метод takeHerHand? Я не определял аннотацию @FallInLove для данного метода! Однако я опредил аннотацию в классе родителе! Оказывается аннотации наследуются. А как же первый поцелуй (firstKiss)? Я его определил в интерфейсе и он не виден у Анжелины!
Тут опытным путем он определят, что аннотации наследуются у прямых потомков классов , но не видны из используемых интерфейсов! Ох уж эти разработчики! Так и норовят нас запутать.
Здесь необходимо дать серьезный коментарий. Действительно по спецификации Java аннотации наследуются только в прямых наследниках и отсутствуют после реализации интерфейса, содержащего аннотации. Их придется добавлять в ручную, или глубже смотреть в класс при помощи reflection перебирая все реализованные интерфейсы, ища методы интерфейсов с аннотациями.
Так мы и посоветуем нашему юному другу, а также настоим, что бы прекратил впустую мечтать и пригласил уже Любку из 11б на свидание. Она согласится!