Как заставить подкласс Java определять аннотацию?

Если класс определил аннотацию, как-то можно заставить свой подкласс определить одну и ту же аннотацию?

Например, у нас есть простая пара классов/подклассов, которые совместно используют @Author @interface. То, что я хотел бы сделать, это заставить каждый последующий подкласс определять ту же аннотацию @Author, предотвращая RuntimeException где-то в будущем.

TestClass.java:

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@interface Author { String name(); }

@Author( name = "foo" )
public abstract class TestClass
{
    public static String getInfo( Class<? extends TestClass> c )
    {
        return c.getAnnotation( Author.class ).name();
    }

    public static void main( String[] args )
    {
        System.out.println( "The test class was written by "
                        + getInfo( TestClass.class ) );
        System.out.println( "The test subclass was written by " 
                        + getInfo( TestSubClass.class ) );
    }
}

TestSubClass.java:

@Author( name = "bar" )
public abstract class TestSubClass extends TestClass {}

Я знаю, что могу перечислить все аннотации во время выполнения и проверить отсутствие @Author, но мне бы очень хотелось сделать это во время компиляции, если это возможно.

Ответ 2

Я уверен, что это невозможно сделать во время компиляции.

Однако это очевидная задача для "unit" -test. Если у вас есть подобные соглашения, которые вы хотели бы применить, но которые могут быть трудными или невозможными для проверки с помощью компилятора, "unit" -tests - это простой способ проверить их.

Другая возможность заключается в реализации пользовательского правила в статическом анализаторе. Здесь также много вариантов.

(Я помещаю блок в кавычки, так как это действительно тест условностей, а не конкретного устройства, но он должен работать вместе с вашими модульными тестами).

Ответ 3

Вы можете сделать аннотацию (например, @EnforceAuthor) с @Inherited в суперклассе и использовать аннотации компилятора (начиная с Java 1.6), чтобы догнать время компиляции. Затем вы имеете ссылку на подкласс и можете проверить, отсутствует ли другая аннотация (например, @Author)). Это позволит отменить компиляцию с сообщением об ошибке.