关于使用自定义注解时,子类覆盖父类注解的问题。
首先自定义两个注解:CustomDescription和CustomDescriptions
package annotation; import java.lang.annotation.*; /** * @author le * date: 2020/11/16 * describe: */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Repeatable(CustomDescriptions.class) @Inherited public @interface CustomDescription { String description() default ""; }
package annotation; import java.lang.annotation.*; /** * @author le * date: 2020/11/16 * describe: */ @Documented @Inherited @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface CustomDescriptions { CustomDescription[] value(); }
再定义两个类来使用自定义的注解:
package annotation.pojo; import annotation.CustomDescription; /** * @author le * date: 2020/11/16 * describe: */ @CustomDescription(description = "基类") @CustomDescription(description = "人1") @CustomDescription(description = "人2") @CustomDescription(description = "人3") @CustomDescription(description = "人4") //Person有五个CustomDescription注解, public class Person { String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
package annotation.pojo; import annotation.CustomDescription; /** * @author le * date: 2020/11/16 * describe: */ @CustomDescription(description = "学生") //@CustomDescription(description = "学生人1") public class Student extends Person { }
用下面的方法获取注解:
package annotation; import annotation.pojo.Student; import org.junit.Test; /** * @author le * date: 2020/11/16 * describe: */ public class CustomDescriptionsTest { //用反射获取注解customDescription @Test public void test1(){ System.out.println("test1尝试获取CustomDescription类型的注解"); CustomDescription customDescriptions = new Student().getClass().getAnnotation(CustomDescription.class); System.out.println(customDescriptions.description()); /*Student有一个description注解的时候正常获取,有两个的时候抛出空指针异常*/ } //用反射获取注解customDescriptions @Test public void test2() { System.out.println("test2尝试获取CustomDescriptions类型的注解"); CustomDescriptions customDescriptions = new Student().getClass().getAnnotation(CustomDescriptions.class); for(CustomDescription customDescriptions1 : customDescriptions.value()){ System.out.println(customDescriptions1.description() + "---customDescription1" ); } } }
遇到的问题是:
为什么Student写一个CustomDescription注解的时候不会覆盖父类的注解,写两个及以上CustomDescription注解的时候就会覆盖父类的注解?
接下来改变Student中CustomDescription的数量:
当Student类只有一个CustomDescription注解的时候:
用test1尝试获取CustomDescription类型的注解,能获取到子类CustomDescription类型的注解;
如果用test2尝试获取CustomDescription数组类型的注解,就会获取到父类CustomDescription数组类型的注解;
结果如下:
test1尝试获取CustomDescription类型的注解 学生 test2尝试获取CustomDescriptions类型的注解 基类---customDescription1 人1---customDescription1 人2---customDescription1 人3---customDescription1 人4---customDescription1
给Student添加注解@CustomDescription(description = "学生人1")
当Student类有两个及两个以上CustomDescription注解的时候:
尝试获取CustomDescription类型的注解,会抛出空指针异常, 此时能获取到子类CustomDescription数组类型的注解,父类CustomDescription数组类型的注解被覆盖掉。
结果如下:
"D:\Program Files\Java\jdk1.8.0_231\bin\java.exe" -ea ...
test1尝试获取CustomDescription类型的注解
java.lang.NullPointerException
at annotation.CustomDescriptionsTest.test1(CustomDescriptionsTest.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
...
test2尝试获取CustomDescriptions类型的注解
学生---customDescription1
学生人1---customDescription1
Process finished with exit code -1
结论:
在上面的测试中,注解有两种类型,一种是CustomDescription类型,另一种是CustomDescription的数组类型。
当一个类中只有一个CustomDescription注解的时候,会以CustomDescription类型存在;当一个类中有两个及两个以上CustomDescription注解的时候,会以CustomDescription数组类型存在;子类和父类如果有相同类型的注解,那么子类就会把父类覆盖掉。
接下来验证上面的结论:
将上面的Person和Student类中的注解数量进行改变,子类注解的数量设为定制一个。
父类的注解数量为一个的时候,运行test1和test2,测试的结果应当是:test1获取到父类的注解,test2获取到子类的注解。
结果如下:
test1尝试获取CustomDescription类型的注解
基类
test2尝试获取CustomDescriptions类型的注解
学生---customDescription1
学生人1---customDescription1
Process finished with exit code 0
父类的注解数量为两个的时候,测试结果应当是:test1抛出异常,test2获取到子类的注解。
结果如下:
test1尝试获取CustomDescription类型的注解
java.lang.NullPointerException
at annotation.CustomDescriptionsTest.test1(CustomDescriptionsTest.java:18)
test2尝试获取CustomDescriptions类型的注解
学生---customDescription1
学生人1---customDescription1