null

Аннотации, блондинки и ожидание Любви

После 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б на свидание. Она согласится!