理解注解中的@Inherited

本文探讨了Java中注解的继承特性,重点讲解了@Inherited元注解的作用及其实现原理。通过实例演示了如何使用@Inherited使注解能够在子类中继承。
@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类型被发现,或者到达类继承结构的顶层。


看下面的例子:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ATable {

public String name() default "";
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface BTable {
public String name() default "";
}


@ATable
public class Super {
private int superx;
public int supery;
public Super() {
}
private int superX(){
return 0;
}
public int superY(){
return 0;
}

}


@BTable
public class Sub extends Super{
private int subx;
public int suby;
private Sub()
{
}
public Sub(int i){
}
private int subX(){
return 0;
}
public int subY(){
return 0;
}
}


public class TestMain {
public static void main(String[] args) {

Class<Sub> clazz = Sub.class;

System.out.println("============================Field===========================");
System.out.println(Arrays.toString(clazz.getFields()));
System.out.println(Arrays.toString(clazz.getDeclaredFields())); //all + 自身
System.out.println("============================Method===========================");
System.out.println(Arrays.toString(clazz.getMethods())); //public + 继承
//all + 自身
System.out.println(Arrays.toString(clazz.getDeclaredMethods()));
System.out.println("============================Constructor===========================");
System.out.println(Arrays.toString(clazz.getConstructors()));
System.out.println(Arrays.toString(clazz.getDeclaredConstructors()));
System.out.println("============================AnnotatedElement===========================");
//注解DBTable2是否存在于元素上
System.out.println(clazz.isAnnotationPresent(BTable.class));
//如果存在该元素的指定类型的注释DBTable2,则返回这些注释,否则返回 null。
System.out.println(clazz.getAnnotation(BTable.class));
//继承
System.out.println(Arrays.toString(clazz.getAnnotations()));
System.out.println(Arrays.toString(clazz.getDeclaredAnnotations())); ////自身
}
}



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


这段程序的运行结果如下:
============================Field===========================
[public int annotion.inherit.Sub.suby, public int annotion.inherit.Super.supery]
[private int annotion.inherit.Sub.subx, public int annotion.inherit.Sub.suby]
============================Method===========================
[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()]
[private int annotion.inherit.Sub.subX(), public int annotion.inherit.Sub.subY()]
============================Constructor===========================
[public annotion.inherit.Sub(int)]
[private annotion.inherit.Sub(), public annotion.inherit.Sub(int)]
============================AnnotatedElement===========================
true
@annotion.inherit.BTable(name=)
[@annotion.inherit.ATable(name=), @annotion.inherit.BTable(name=)]
[@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去掉。那么后面四行的输出结果为:
true
@annotion.inherit.BTable(name=)
[@annotion.inherit.BTable(name=)]
[@annotion.inherit.BTable(name=)]

[b]无法获取到@ATable的注解,
也就是说注解和普通类的区别是如果一个子类想获取到父类上的注解信息,
那么必须在父类上使用的注解上面 加上@Inherit关键字
[/b]
### Java 注解(Annotation)原理及使用详解 Java 注解是一种元数据,它可以被添加到 Java 代码中,例如类、方法、变量、参数等,以提供额外的信息。这些信息可以被编译器、运行时系统或其他工具使用,以执行特定的逻辑或生成代码。注解不会直接影响代码的逻辑,但可以通过反射机制在运行时读取,并根据注解的内容做出相应处理。 #### 注解的基本概念 Java 注解本质上是一个接口,它继承自 `java.lang.annotation.Annotation` 接口。注解可以包含成员变量,但这些变量必须是基本类型、String、Class、Enum、Annotation 或者这些类型的数组。注解本身不会执行任何操作,它的作用是为代码提供元数据,供其他工具或框架解析和使用。 #### 注解的分类 Java 注解分为三类: 1. **标准注解**:Java 自带的注解,如 `@Override`、`@Deprecated`、`@SuppressWarnings` 等,用于标记代码的特定行为。 2. **元注解**:用于定义其他注解注解,如 `@Retention`、`@Target`、`@Inherited`、`@Documented` 等。 3. **自定义注解**:开发者根据需求自定义的注解,用于特定的业务场景。 #### 元注解详解 - `@Retention`:指定注解的生命周期,可以是 `SOURCE`(仅在源码中存在,编译时丢弃)、`CLASS`(默认,编译时保留,但运行时不可用)或 `RUNTIME`(运行时保留,可以通过反射获取)。 - `@Target`:指定注解可以应用的程序元素类型,如 `TYPE`(类、接口、枚举)、`METHOD`(方法)、`FIELD`(字段)等。 - `@Inherited`:表示注解可以被子类继承。 - `@Documented`:表示注解应该被包含在 JavaDoc 中。 #### 注解的使用 以下是一个简单的自定义注解示例: ```java import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface HelloAnnotation { String say() default "Hello"; } ``` 该注解可以被应用到类上,并且在运行时可以通过反射获取: ```java @HelloAnnotation(say = "Do it!") public class TestMain { public static void main(String[] args) { HelloAnnotation annotation = TestMain.class.getAnnotation(HelloAnnotation.class); System.out.println(annotation.say()); } } ``` #### 注解的解析 Java 提供了 `java.lang.reflect.AnnotatedElement` 接口来获取注解信息。常用的获取注解的方法包括: - `getAnnotation(Class<T> annotationClass)`:获取指定类型的注解。 - `getAnnotations()`:获取所有注解。 - `isAnnotationPresent(Class<? extends Annotation> annotationClass)`:判断是否包含指定类型的注解。 #### Android 开源库中的注解应用 许多 Android 开源库利用注解来简化开发流程,例如 ButterKnife 使用 `@BindView` 注解来绑定视图控件,Dagger 使用 `@Inject` 注解来实现依赖注入。这些库通常在编译时通过注解处理器生成代码,从而在运行时提高性能并减少样板代码。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值