注解

@Target:设置该注解的应用场合。

  • value:ElementType[]
    • PACKAGE
      包定义
    • TYPE
      类/接口/注解/枚举 + 定义
    • ANNOTATION_TYPE
      注解定义
    • TYPE_PARAMETER
      泛型定义
    • TYPE_USE
      类/接口/注解/枚举/泛型 + 定义/应用
    • FIELD
      字段定义
    • CONSTRUCTOR
      构造器定义
    • METHOD
      方法定义
    • PARAMETER
      参数定义
    • LOCAL_VARIABLE
      局部变量定义

 

用例1:注解包定义

test/Test.java

public class Test {
    public static void main(String[] params) {
        Annotation[] annotations = Package.getPackage("test").getAnnotations();
        System.out.println(Arrays.toString(annotations));
        // 输出结果:[@test.Test$TestAnnotation()]
    }
    
    @Target(ElementType.PACKAGE)
    @Retention(RetentionPolicy.RUNTIME)
    public static @interface TestAnnotation {

    }
}

test/package-info.java

@test.Test.TestAnnotation
package test;

 

用例2:注解类/接口/注解/枚举 + 定义

public class Test {
    public static void main(String[] params) {
        System.out.println(Arrays.toString(MyClass.class.getAnnotations()));
        System.out.println(Arrays.toString(MyInterface.class.getAnnotations()));
        System.out.println(Arrays.toString(MyAnnotation.class.getAnnotations()));
        System.out.println(Arrays.toString(MyEnum.class.getAnnotations()));
        
        /*
            输出结果:
            [@test.Test$TestAnnotation(value=类定义)]
            [@test.Test$TestAnnotation(value=接口定义)]
            [@test.Test$TestAnnotation(value=注解定义)]
            [@test.Test$TestAnnotation(value=枚举定义)]
         */
    }
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public static @interface TestAnnotation {
        String value();
    }
    
    @TestAnnotation("类定义")
    public class MyClass {
        
    }

    @TestAnnotation("接口定义")
    public interface MyInterface {
        
    }

    @TestAnnotation("注解定义")
    public @interface MyAnnotation {
        
    }

    @TestAnnotation("枚举定义")
    public enum MyEnum {
        
    }
    
    // 编译错误:不允许注解泛型
    /*public class MyGeneric<@TestAnnotation("泛型定义") T> {
        
    }*/
}

 

用例3:注解泛型定义

public class Test {
    public static void main(String[] params) {
        System.out.println(Arrays.toString(MyGeneric.class.getTypeParameters()[0].getAnnotations()));
        
        /*
            输出结果:
            [@test.Test$TestAnnotation(value=泛型定义)]
         */
    }
    
    @Target(ElementType.TYPE_PARAMETER)
    @Retention(RetentionPolicy.RUNTIME)
    public static @interface TestAnnotation {
        String value();
    }
    
    public class MyGeneric<@TestAnnotation("泛型定义") T> {
        
    }
}

 

用例4: 注解类/接口/注解/枚举/泛型 + 定义/应用

public class Test<@TestAnnotation("泛型定义") T> {
    public static void main(String[] params) throws NoSuchFieldException, SecurityException, NoSuchMethodException {
        test1();
        System.out.println("--------------------------------------------------------------------------");
        test2();
    }

    public static void test1(){
        System.out.println(Arrays.toString(MyClass.class.getAnnotations()));
        System.out.println(Arrays.toString(MyInterface.class.getAnnotations()));
        System.out.println(Arrays.toString(MyAnnotation.class.getAnnotations()));
        System.out.println(Arrays.toString(MyEnum.class.getAnnotations()));
        System.out.println(Arrays.toString(Test.class.getTypeParameters()[0].getAnnotations()));
        /*
            输出结果:
            [@test.Test$TestAnnotation(value=类定义)]
            [@test.Test$TestAnnotation(value=接口定义)]
            []
            [@test.Test$TestAnnotation(value=枚举定义)]
            [@test.Test$TestAnnotation(value=泛型定义)]
         */
    }

    @Target(ElementType.TYPE_USE)
    @Retention(RetentionPolicy.RUNTIME)
    public static @interface TestAnnotation {
        String value();
    }

    @TestAnnotation("类定义")
    public static class MyClass {
        // 注:可编译通过,但无实际效果
        @TestAnnotation("字段定义")
        private int myField;
    }

    @TestAnnotation("接口定义")
    public static interface MyInterface {

    }

    // 注:可编译通过,但无实际效果
    @TestAnnotation("注解定义")
    public static @interface MyAnnotation {

    }

    @TestAnnotation("枚举定义")
    public static enum MyEnum {

    }
    
    public static void test2() throws NoSuchFieldException, SecurityException, NoSuchMethodException{
        System.out.println(Arrays.toString(MySubClass.class.getAnnotatedSuperclass().getAnnotations()));
        System.out.println(Arrays.toString(MyImplClass.class.getAnnotatedInterfaces()[0].getAnnotations()));
        System.out.println(Arrays.toString(Test.class.getDeclaredField("myClassField").getAnnotatedType().getAnnotations()));
        System.out.println(Arrays.toString(Test.class.getDeclaredField("myInterfaceField").getAnnotatedType().getAnnotations()));
        System.out.println(Arrays.toString(Test.class.getDeclaredField("myEnumField").getAnnotatedType().getAnnotations()));
        System.out.println(Arrays.toString(Test.class.getDeclaredField("myGenericField").getAnnotatedType().getAnnotations()));
        /*
            输出结果:
            [@test.Test$TestAnnotation(value=类继承应用)]
            [@test.Test$TestAnnotation(value=接口实现应用)]
            [@test.Test$TestAnnotation(value=类定义字段应用)]
            [@test.Test$TestAnnotation(value=接口定义字段应用)]
            [@test.Test$TestAnnotation(value=枚举定义字段应用)]
            [@test.Test$TestAnnotation(value=泛型定义字段应用)]
         */
    }
    
    public static class MySubClass extends @TestAnnotation("类继承应用") MyClass {
        
    }
    
    public static class MyImplClass implements @TestAnnotation("接口实现应用") MyInterface {
        
    }

    // 注:可编译通过,但无实际效果
    @TestAnnotation("字段定义")
    private int myField;
    
    private @TestAnnotation("类定义字段应用") MyClass myClassField;
    
    private @TestAnnotation("接口定义字段应用") MyInterface myInterfaceField;
    
    private @TestAnnotation("枚举定义字段应用") MyEnum myEnumField;
    
    private @TestAnnotation("泛型定义字段应用") T myGenericField;
}

 

@Retention:设置目标注解的保留策略。

  • value:RetentionPolicy
    • SOURCE
      源文件
    • CLASS
      类文件
    • RUNTIME
      运行时

 

@Inherited:表示目标注解用于类定义时,类的子类是否可继承该注解。

 

@Repeatable:表示目标注解可以多次应用于同一个场合。

  • value():Class<? extends Annotation>

 

@Documented:表示目标注解可被工具生成文档。

 

@Override:表示目标方法是继承或实现而来的。

 

@Deprecated:表示目标已不建议使用。

 

@SuppressWarnings:过滤一些编辑器的警告。

 

@InterfaceFunction:表示目标接口是一个接口函数式,只有一个未实现且非静态的方法,其它方法可以是默认或静态方法。

 

不解之迷:照理说,这不应该出现的问题。

public class Test {
    public static void main(String[] params) {
        System.out.println(Arrays.toString(TestClass.class.getAnnotatedSuperclass().getAnnotations()));
        
        // 输出结果:
        // AnnotationFormatError: Duplicate annotation
    }
    
    public static class TestSuperClass{
        
    }
    
    public static class TestClass extends @TestInterface2({@TestInterface1(1), @TestInterface1(2)}) TestSuperClass{
        
    }
    
    @Target({ ElementType.TYPE_USE })
    @Retention(RetentionPolicy.RUNTIME)
    public static @interface TestInterface1{
        int value();
    }
    
    @Target({ ElementType.TYPE_USE })
    @Retention(RetentionPolicy.RUNTIME)
    public static @interface TestInterface2{
        TestInterface1[] value();
    }
}

  

解决方案1:TestInterface1删除@Retention

public class Test {
    public static void main(String[] params) {
        System.out.println(Arrays.toString(TestClass.class.getAnnotatedSuperclass().getAnnotations()));
        
        // 输出结果:
        // [@Test$TestInterface2(value=[@Test$TestInterface1(value=1), @Test$TestInterface1(value=2)])]
    }
    
    public static class TestSuperClass{
        
    }
    
    public static class TestClass extends @TestInterface2({@TestInterface1(1), @TestInterface1(2)}) TestSuperClass{
        
    }
    
    @Target({ ElementType.TYPE_USE })
    public static @interface TestInterface1{
        int value();
    }
    
    @Target({ ElementType.TYPE_USE })
    @Retention(RetentionPolicy.RUNTIME)
    public static @interface TestInterface2{
        TestInterface1[] value();
    }
}

  

解决方案2:在TestInterface1上使用@Repeatable

public class Test {
    public static void main(String[] params) {
        System.out.println(Arrays.toString(TestClass.class.getAnnotatedSuperclass().getAnnotations()));
        
        // 输出结果:
        // [@Test$TestInterface2(value=[@Test$TestInterface1(value=1), @Test$TestInterface1(value=2)])]
    }
    
    public static class TestSuperClass{
        
    }
    
    public static class TestClass extends @TestInterface1(1) @TestInterface1(2) TestSuperClass{
        
    }
    
    @Target({ ElementType.TYPE_USE })
    @Retention(RetentionPolicy.RUNTIME)
    @Repeatable(TestInterface2.class)
    public static @interface TestInterface1{
        int value();
    }
    
    @Target({ ElementType.TYPE_USE })
    @Retention(RetentionPolicy.RUNTIME)
    public static @interface TestInterface2{
        TestInterface1[] value();
    }
}

 

posted @ 2017-01-08 21:40  突破渴望  阅读(243)  评论(0编辑  收藏  举报