理解注解中的@Inherited

本文深入解析Java中@Inherited元注解的作用及应用,通过实例代码演示如何实现注解的继承特性,适用于Java类及其子类。探讨了不同注解保留策略对继承的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

@Inherited:
@Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。
如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。



注意:@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,
方法并不从它所重载的方法继承annotation。

  当@Inherited annotation类型标注的annotation的Retention是RetentionPolicy.RUNTIME,则反射API增强了这种继承性。
如果我们使用java.lang.reflect去查询一个@Inherited annotation类型的annotation时,反射代码检查将展开工作:
检查class和其父类,直到发现指定的annotation类型被发现,或者到达类继承结构的顶层。


看下面的例子:
Java代码
  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Inherited
  4. public @interface ATable {
  5. public String name() default "";
  6. }
  7. @Target(ElementType.TYPE)
  8. @Retention(RetentionPolicy.RUNTIME)
  9. public @interface BTable {
  10. public String name() default "";
  11. }
  12. @ATable
  13. public class Super {
  14. private int superx;
  15. public int supery;
  16. public Super() {
  17. }
  18. private int superX(){
  19. return 0;
  20. }
  21. public int superY(){
  22. return 0;
  23. }
  24. }
  25. @BTable
  26. public class Sub extends Super{
  27. private int subx;
  28. public int suby;
  29. private Sub()
  30. {
  31. }
  32. public Sub(int i){
  33. }
  34. private int subX(){
  35. return 0;
  36. }
  37. public int subY(){
  38. return 0;
  39. }
  40. }
  41. public class TestMain {
  42. public static void main(String[] args) {
  43. Class<Sub> clazz = Sub.class;
  44. System.out.println("============================Field===========================");
  45. System.out.println(Arrays.toString(clazz.getFields()));
  46. System.out.println(Arrays.toString(clazz.getDeclaredFields())); //all + 自身
  47. System.out.println("============================Method===========================");
  48. System.out.println(Arrays.toString(clazz.getMethods())); //public + 继承
  49. //all + 自身
  50. System.out.println(Arrays.toString(clazz.getDeclaredMethods()));
  51. System.out.println("============================Constructor===========================");
  52. System.out.println(Arrays.toString(clazz.getConstructors()));
  53. System.out.println(Arrays.toString(clazz.getDeclaredConstructors()));
  54. System.out.println("============================AnnotatedElement===========================");
  55. //注解DBTable2是否存在于元素上
  56. System.out.println(clazz.isAnnotationPresent(BTable.class));
  57. //如果存在该元素的指定类型的注释DBTable2,则返回这些注释,否则返回 null。
  58. System.out.println(clazz.getAnnotation(BTable.class));
  59. //继承
  60. System.out.println(Arrays.toString(clazz.getAnnotations()));
  61. System.out.println(Arrays.toString(clazz.getDeclaredAnnotations())); ////自身
  62. }
  63. }



分析下这段代码,这里定义了两个annotion,其中ATable使用了@Inherited, BTable没有使用
@Inherited,类Super和类Sub分别使用了ATable和BTable这两个注解,并且Sub类 继承Super类。


这段程序的运行结果如下:
Java代码
  1. ============================Field===========================
  2. [public int annotion.inherit.Sub.suby, public int annotion.inherit.Super.supery]
  3. [private int annotion.inherit.Sub.subx, public int annotion.inherit.Sub.suby]
  4. ============================Method===========================
  5. [public int annotion.inherit.Sub.subY(), public int annotion.inherit.Super.superY(), public final void java.lang.Object.wait() throws java.lang.InterruptedException, public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public boolean java.lang.Object.equals(java.lang.Object), public java.lang.String java.lang.Object.toString(), public native int java.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.getClass(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll()]
  6. [private int annotion.inherit.Sub.subX(), public int annotion.inherit.Sub.subY()]
  7. ============================Constructor===========================
  8. [public annotion.inherit.Sub(int)]
  9. [private annotion.inherit.Sub(), public annotion.inherit.Sub(int)]
  10. ============================AnnotatedElement===========================
  11. true
  12. @annotion.inherit.BTable(name=)
  13. [@annotion.inherit.ATable(name=), @annotion.inherit.BTable(name=)]
  14. [@annotion.inherit.BTable(name=)]




getFields()获得某个类的所有的公共(public)的字段,包括父类。
getDeclaredFields()获得某个类的所有申明的字段,即包括public、private和proteced,
但是不包括父类的申明字段。 同样类似的还有getConstructors()和getDeclaredConstructors(),
getMethods()和getDeclaredMethods()。

因此:Field的打印好理解,因为sub是super类的子类,会继承super的类
同样method和constructor的打印也是如此。

clazz.getAnnotations()可以打印出当前类的注解和父类的注解
clazz.getDeclaredAnnotations()只会打印出当前类的注解

如果注解ATable把@Inherit去掉。那么后面四行的输出结果为:
Java代码
  1. true
  2. @annotion.inherit.BTable(name=)
  3. [@annotion.inherit.BTable(name=)]
  4. [@annotion.inherit.BTable(name=)]

无法获取到@ATable的注解,
也就是说注解和普通类的区别是如果一个子类想获取到父类上的注解信息,
那么必须在父类上使用的注解上面 加上@Inherit关键字 


转载于:https://juejin.im/post/5c63e2b0f265da2dd94c8e16

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值