1. 元注解@Inherited继承
package com.example.demo;
import java.lang.annotation.*;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
Annotation[] superAnnos = SuperClass.class.getAnnotations();
System.out.println(Arrays.toString(superAnnos));
Annotation[] childAnnos = ChildClass.class.getAnnotations();
System.out.println(Arrays.toString(childAnnos));
}
}
@Target(value = ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
@Inherited // 声明注解具有继承性
@interface InheritedAnno {
String value() default "InheritedAnno";
}
@InheritedAnno
class SuperClass{
}
class ChildClass extends SuperClass{ // 子类可以继承父类的注解
}
2.属性和方法注解的继承性
在属性和方法上的注解不同于在类上的注解,它们的特殊性在于如果子类继承的方法在父类中有注解,那么这些方法和属性是可以继承下来的。但是如果子类的方法如果进行了重写,那么重写后的方法是不会有父类对应方法中的注解的。如果是父接口方法上面带有注解, 因为接口方法必须要实现(相当于重写),所以实现父接口的方法上不能继承注解。
package com.example.demo;
import java.lang.annotation.*;
import java.util.Arrays;
public class Test {
public static void main(String[] args) throws Exception{
Annotation[] field1Annos = ChildClass.class.getField("field1").getAnnotations();
System.out.println(Arrays.toString(field1Annos));
Annotation[] method1Annos = ChildClass.class.getMethod("method1").getAnnotations();;
System.out.println(Arrays.toString(method1Annos));
Annotation[] method1OverrideAnnos = ChildClass2.class.getMethod("method1").getAnnotations();
System.out.println(Arrays.toString(method1OverrideAnnos));
}
}
@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
@interface MethodAnno {
String value() default "AMethod";
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldAnno{
String value() default "AField";
}
class SuperClass{
@FieldAnno
public int field1 = 100; // 必须使用public,否则反射查找子类该字段时会抛出找不到的异常
@MethodAnno
public void method1(){
System.out.println("super.method1");
}
}
class ChildClass extends SuperClass{ // 子类可以继承父类的注解
}
class ChildClass2 extends SuperClass{
@Override
public void method1(){
System.out.println("child.method1");
}
}
3. ElementType.TYPE的注解
该种注解可以用来注解其它注解,很多人认为这时一种注解的合并,其实这种看法时错误的。
// @SpringBootApplication的定义
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
}
/* 使用@SpringBootApplication,其实等价于使用了下面的四个注解:@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan、@SpringBootApplication。
从java层面的原理来讲,并不是@SpringBootApplication内部包含(或者认为合并了)另外的三个注解,而是另外的三个注解修饰@SpringBootApplication这个注解,如果要获取其它三个注解的值,那么必须通过SpringBootApplication.class.getAnnotations()的方法获取。
*/
package com.example.demo;
import java.lang.annotation.*;
import java.util.Arrays;
@AnnoC
public class Test {
public static void main(String[] args) throws Exception{
Annotation[] annos = Test.class.getAnnotations();
System.out.println(Arrays.toString(annos));
AnnoC annoC = (AnnoC)annos[0];
System.out.println(annoC.valueC());
AnnoB annoB = AnnoC.class.getAnnotation(AnnoB.class);
System.out.println(annoB.valueB());
Annotation [] annos2 = AnnoC.class.getAnnotations();
System.out.println(Arrays.toString(annos2));
}
}
@Target(value = ElementType.TYPE) //TYPE可以用于注解其它注解
@Retention(value = RetentionPolicy.RUNTIME)
@interface AnnoA{
String valueA() default "A";
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface AnnoB{
String valueB() default "B";
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@AnnoA
@AnnoB
@interface AnnoC{ // AnnoC上有四个注解,AnnoC也是一个类
String valueC() default "C";
}