文章内容
我们知道在编写自定义注解时,可以通过指定@Inherited注解,指明自定义注解是否可以被继承。但实现情况又可细分为多种。子类可以继承到父类上的注解吗?
一、测试环境
- 父类的类上和方法上有自定义的注解——MyAnnotation
- 子类继承了这个父类,分别:
- 子类方法,实现了父类上的抽象方法
- 子类方法,继承了父类上的方法
- 子类方法,覆盖了父类上的方法
二、代码实现
1、MyAnnotation自定义注解
01 02 03 04 05 06 07 08 09 10 11 12 | import java.lang.annotation.Inherited; import java.lang.annotation.Retention; /** * 自定义注解 */ // @Inherited //可以被继承 @Retention (java.lang.annotation.RetentionPolicy.RUNTIME) //可以通过反射读取注解 public @interface MyAnnotation { String value(); } |
2、父类
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 | @MyAnnotation (value = "类名上的注解" ) public abstract class ParentClass { @MyAnnotation (value = "父类的abstractMethod方法" ) public abstract void abstractMethod(); @MyAnnotation (value = "父类的doExtends方法" ) public void doExtends() { System.out.println( " ParentClass doExtends ..." ); } @MyAnnotation (value = "父类的doHandle方法" ) public void doHandle(){ System.out.println( " ParentClass doHandle ..." ); } } |
3、子类
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 | public class SubClass extends ParentClass{ //子类实现父类的抽象方法 @Override public void abstractMethod() { System.out.println( "子类实现父类的abstractMethod抽象方法" ); } //子类继承父类的doExtends方法 //子类覆盖父类的doHandle方法 @Override public void doHandle(){ System.out.println( "子类覆盖父类的doHandle方法" ); } } |
4、测试类
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | import java.lang.reflect.Method; public class MainTest { public static void main(String[] args) throws SecurityException, NoSuchMethodException { Class<SubClass> clazz = SubClass. class ; if (clazz.isAnnotationPresent(MyAnnotation. class )) { MyAnnotation cla = clazz.getAnnotation(MyAnnotation. class ); System.out.println( "子类继承到父类类上Annotation,其信息如下:" +cla.value()); } else { System.out.println( "子类没有继承到父类类上Annotation" ); } // 实现抽象方法测试 Method method = clazz.getMethod( "abstractMethod" , new Class[] {}); if (method.isAnnotationPresent(MyAnnotation. class )) { MyAnnotation ma = method.getAnnotation(MyAnnotation. class ); System.out.println( "子类实现父类的abstractMethod抽象方法,继承到父类抽象方法中的Annotation,其信息如下:" +ma.value()); } else { System.out.println( "子类实现父类的abstractMethod抽象方法,没有继承到父类抽象方法中的Annotation" ); } //覆盖测试 Method methodOverride = clazz.getMethod( "doExtends" , new Class[] {}); if (methodOverride.isAnnotationPresent(MyAnnotation. class )) { MyAnnotation ma = methodOverride.getAnnotation(MyAnnotation. class ); System.out.println( "子类继承父类的doExtends方法,继承到父类doExtends方法中的Annotation,其信息如下:" +ma.value()); } else { System.out.println( "子类继承父类的doExtends方法,没有继承到父类doExtends方法中的Annotation" ); } //继承测试 Method method3 = clazz.getMethod( "doHandle" , new Class[] {}); if (method3.isAnnotationPresent(MyAnnotation. class )) { MyAnnotation ma = method3.getAnnotation(MyAnnotation. class ); System.out.println( "子类覆盖父类的doHandle方法,继承到父类doHandle方法中的Annotation,其信息如下:" +ma.value()); } else { System.out.println( "子类覆盖父类的doHandle方法,没有继承到父类doHandle方法中的Annotation" ); } } } |
三、运行结果
1、编写自定义注解时未写@Inherited的运行结果
1 2 3 4 | 子类没有继承到父类类上Annotation 子类实现父类的abstractMethod抽象方法,没有继承到父类抽象方法中的Annotation 子类继承父类的doExtends方法,继承到父类doExtends方法中的Annotation,其信息如下:父类的doExtends方法 子类覆盖父类的doHandle方法,没有继承到父类doHandle方法中的Annotation |
2、编写自定义注解时写了@Inherited的运行结果
1 2 3 4 | 子类继承到父类类上Annotation,其信息如下:类名上的注解 子类实现父类的abstractMethod抽象方法,没有继承到父类抽象方法中的Annotation 子类继承父类的doExtends方法,继承到父类doExtends方法中的Annotation,其信息如下:父类的doExtends方法 子类覆盖父类的doHandle方法,没有继承到父类doHandle方法中的Annotation |
四、结论
父类的类上和方法上有自定义的注解,子类继承了这个父类,的情况下。
编写自定义注解时未写@Inherited的运行结果: | 编写自定义注解时写了@Inherited的运行结果: | |
---|---|---|
子类的类上能否继承到父类的类上的注解? | 否 | 能 |
子类方法,实现了父类上的抽象方法,这个方法能否继承到注解? | 否 | 否 |
子类方法,继承了父类上的方法,这个方法能否继承到注解? | 能 | 能 |
子类方法,覆盖了父类上的方法,这个方法能否继承到注解? | 否 | 否 |
我们知道在编写自定义注解时,可以通过指定@Inherited注解,指明自定义注解是否可以被继承。通过测试结果来看:
@Inherited 只是可控制 对类名上注解是否可以被继承。不能控制方法上的注解是否可以被继承。
五、附注
Spring 实现事务的注解@Transactional 是可以被继承的,通过查看它的源码可以看到@Inherited。