@Target:设置该注解的应用场合。
- value:ElementType[]
- PACKAGE
包定义 - TYPE
类/接口/注解/枚举 + 定义 - ANNOTATION_TYPE
注解定义 - TYPE_PARAMETER
泛型定义 - TYPE_USE
类/接口/注解/枚举/泛型 + 定义/应用 - FIELD
字段定义 - CONSTRUCTOR
构造器定义 - METHOD
方法定义 - PARAMETER
参数定义 - LOCAL_VARIABLE
局部变量定义
- PACKAGE
用例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
运行时
- SOURCE
@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(); } }