Annotation的架构图:
可以看出:
(01) 1个Annotation 和 1个RetentionPolicy关联。
可以理解为:每1个Annotation对象,都会有唯一的RetentionPolicy属性。
(02) 1个Annotation 和 1~n个ElementType关联。
可以理解为:对于每1个Annotation对象,可以有若干个ElementType属性。
(03) Annotation 有许多实现类,包括:Deprecated, Documented, Inherited, Override等等。
Annotation 的每一个实现类,都“和1个RetentionPolicy关联”并且“和1~n个ElementType关联”。
Annotation组成成分
Annotation.java
package java.lang.annotation;public interfaceAnnotation {
boolean equals(Object obj);inthashCode();
String toString();
Class extends Annotation>annotationType();
}
ElementType.java
package java.lang.annotation;public enumElementType {
TYPE,/*类、接口(包括注释类型)或枚举声明*/FIELD,/*字段声明(包括枚举常量)*/METHOD,/*方法声明*/PARAMETER,/*参数声明*/CONSTRUCTOR,/*构造方法声明*/LOCAL_VARIABLE,/*局部变量声明*/ANNOTATION_TYPE,/*注释类型声明*/PACKAGE/*包声明*/}
RetentionPolicy.java
package java.lang.annotation;public enumRetentionPolicy {
SOURCE,/*Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该Annotation信息了*/CLASS,/*编译器将Annotation存储于类对应的.class文件中。默认行为*/RUNTIME/*编译器将Annotation存储于class文件中,并且可由JVM读入*/}
说明:
(01) Annotation 是个接口。
“每1个Annotation” 都与 “1个RetentionPolicy”关联,并且与 “1~n个ElementType”关联。可以通俗的理解为:每1个Annotation对象,都会有唯一的RetentionPolicy属性;至于ElementType属性,则有1~n个。
(02) ElementType 是Enum枚举类型,用来指定Annotation的类型。
“每1个Annotation” 都与 “1~n个ElementType”关联。当Annotation与某个ElementType关联时,就意味着:Annotation有了某种用途。
例如,若一个Annotation对象是METHOD类型,则该Annotation只能用来修饰方法。
(03) RetentionPolicy 是Enum枚举类型,用来指定Annotation的策略。通俗点说,就是不同RetentionPolicy类型的Annotation的作用域不同。
“每1个Annotation” 都与 “1个RetentionPolicy”关联。
a) 若Annotation的类型为 SOURCE,则意味着:Annotation仅存在于编译器处理期间,编译器处理完之后,该Annotation就没用了。
例如,“ @Override ”标志就是一个Annotation。当它修饰一个方法的时候,就意味着该方法覆盖父类的方法;并且在编译期间会进行语法检查!编译器处理完 后,“@Override”就没有任何作用了。
b) 若Annotation的类型为 CLASS,则意味着:编译器将Annotation存储于类对应的.class文件中,是Annotation的默认行为。
c) 若Annotation的类型为 RUNTIME,则意味着:编译器将Annotation存储于class文件中,并且可由JVM读入。
这时,只需要记住“每1个Annotation” 都与 “1个RetentionPolicy”关联,并且与 “1~n个ElementType”关联。
示例
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)public@interface MyAnnotation1 {
}
说明:
定义一个Annotation,名字是MyAnnotation1。定义了MyAnnotation1之后,可以在代码中通过“@MyAnnotation1”来使用它。
其它的,@Documented, @Target, @Retention, @interface都是来修饰MyAnnotation1的。下面分别说说它们的含义:
(01) @interface
使用@interface定义注解时,意味着它实现java.lang.annotation.Annotation接口,即该注解就是一个Annotation。
定义Annotation时,@interface是必须的
注意:和我们通常的implemented实现接口的方法不同。Annotation接口的实现细节都由编译器完成。通过@interface定义注解后,该注解不能继承其他的注解或接口。
(02) @Documented
类和方法的Annotation在缺省情况下是不出现在javadoc中的。如果使用@Documented修饰该Annotation,则表示它可以出现在javadoc中。
定义Annotation时,@Documented可有可无;若没有定义,则Annotation不会出现在javadoc中。
(03) @Target(ElementType.TYPE)
ElementType 是Annotation的类型属性。而@Target的作用,就是来指定Annotation的类型属性。
@Target(ElementType.TYPE) 的意思就是指定该Annotation的类型是ElementType.TYPE。这就意味着,MyAnnotation1是来修饰“类、接口(包括注释类型)或枚举声明”的注解。
定义Annotation时,@Target可有可无。若有@Target,则该Annotation只能用于它所指定的地方;若没有@Target,则该Annotation可以用于任何地方。
(04) @Retention(RetentionPolicy.RUNTIME)
RetentionPolicy 是Annotation的策略属性,而@Retention的作用,就是指定Annotation的策略属性。
@Retention(RetentionPolicy.RUNTIME) 的意思就是指定该Annotation的策略是RetentionPolicy.RUNTIME。这就意味着,编译器会将该Annotation信息保留在.class文件中,并且能被虚拟机读取。
定义Annotation时,@Retention可有可无。若没有@Retention,则默认是RetentionPolicy.CLASS。
Annotation
@interface用来声明Annotation,@Documented用来表示该Annotation是否会出现在javadoc中, @Target用来指定Annotation的类型,@Retention用来指定Annotation的策略。
java 常用的Annotation:
@Deprecated -- @Deprecated 所标注内容,不再被建议使用。
@Override-- @Override 只能标注方法,表示该方法覆盖父类中的方法。
@Documented-- @Documented 所标注内容,可以出现在javadoc中。
@Inherited-- @Inherited只能被用来标注“Annotation类型”,它所标注的Annotation具有继承性。
@Retention-- @Retention只能被用来标注“Annotation类型”,而且它被用来指定Annotation的RetentionPolicy属性。
@Target-- @Target只能被用来标注“Annotation类型”,而且它被用来指定Annotation的ElementType属性。
@SuppressWarnings-- @SuppressWarnings 所标注内容产生的警告,编译器会对这些警告保持静默。
@Deprecated 的定义如下:
@Documented
@Retention(RetentionPolicy.RUNTIME)public@interface Deprecated {
}
说明:
(01) @interface -- 它的用来修饰Deprecated,意味着Deprecated实现了java.lang.annotation.Annotation接口;即Deprecated就是一个注解。
(02) @Documented -- 作用是说明该注解能出现在javadoc中。
(03) @Retention(RetentionPolicy.RUNTIME) -- 它的作用是指定Deprecated的策略是RetentionPolicy.RUNTIME。这就意味着,编译器会将Deprecated的信息保留在.class文件中,并且能被虚拟机读取。
(04) @Deprecated 所标注内容,不再被建议使用。
@Inherited 的定义如下
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)public@interface Inherited {
}
说明:
(01) @interface -- 用来修饰Inherited,意味着Inherited实现了java.lang.annotation.Annotation接口;即Inherited就是一个注解。
(02) @Documented -- 作用是说明该注解能出现在javadoc中。
(03) @Retention(RetentionPolicy.RUNTIME) -- 作用是指定Inherited的策略是RetentionPolicy.RUNTIME。这就意味着,编译器会将Inherited的信息保留在.class文件中,并且能被虚拟机读取。
(04) @Target(ElementType.ANNOTATION_TYPE) -- 作用是指定Inherited的类型是ANNOTATION_TYPE。这就意味着,@Inherited只能被用来标注“Annotation类型”。
(05) @Inherited 的含义是,它所标注的Annotation将具有继承性。
定义了某个Annotaion,名称是MyAnnotation,并且MyAnnotation被标注为@Inherited。某个类Base使用了MyAnnotation,则Base具有了“具有了注解MyAnnotation”;Sub继承了Base,由于MyAnnotation是@Inherited的(具有继承性),所以,Sub也“具有了注解MyAnnotation”。
/**
* @Inherited 演示示例
**/package com.skywang.annotation;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Inherited;/**
* 自定义的Annotation。*/@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@interface Inheritable
{
}
@InheritableclassInheritableFather
{publicInheritableFather() {//InheritableBase是否具有 Inheritable Annotation
System.out.println("InheritableFather:"+InheritableFather.class.isAnnotationPresent(Inheritable.class));
}
}/**
* InheritableSon 类只是继承于 InheritableFather,*/
public classInheritableSon extends InheritableFather
{publicInheritableSon() {
super();//调用父类的构造函数//InheritableSon类是否具有 Inheritable Annotation
System.out.println("InheritableSon:"+InheritableSon.class.isAnnotationPresent(Inheritable.class));
}public static voidmain(String[] args)
{
InheritableSonis = newInheritableSon();
}
}
结果:true true
对InheritableSon.java进行修改:注释掉“Inheritable的@Inherited注解”:返回 true false
@SuppressWarnings 的定义如下:
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)public@interface SuppressWarnings {
String[] value();
}
说明:
(01) @interface -- 它的用来修饰SuppressWarnings,意味着SuppressWarnings实现java.lang.annotation.Annotation接口;即SuppressWarnings就是一个注解。
(02) @Retention(RetentionPolicy.SOURCE) -- 作用是指定SuppressWarnings的策略是RetentionPolicy.SOURCE。意味着,SuppressWarnings信息仅存在于编译器处理期间,编译器处理完之后SuppressWarnings就没有作用了。
(03) @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) -- 它的作用是指定SuppressWarnings的类型同时包括TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE。
TYPE意味着,它能标注“类、接口(包括注释类型)或枚举声明”。
FIELD意味着,它能标注“字段声明”。
METHOD意味着,它能标注“方法”。
PARAMETER意味着,它能标注“参数”。
CONSTRUCTOR意味着,它能标注“构造方法”。
LOCAL_VARIABLE意味着,它能标注“局部变量”。
(04) String[] value(); 意味着,SuppressWarnings能指定参数
(05) SuppressWarnings 的作用是,让编译器对“它所标注的内容”的某些警告保持静默。例如,"@SuppressWarnings(value={"deprecation", "unchecked"})" 表示对“它所标注的内容”中的 “SuppressWarnings不再建议使用警告”和“未检查的转换时的警告”保持沉默。
作用:
让编译器进行编译检查的作用
若某个方法被 @Override的 标注,则意味着该方法会覆盖父类中的同名方法。如果有方法被@Override标示,但父类中却没有“被@Override标注”的同名方法,则编译器会报错
反射中使用Annotation
import java.lang.annotation.Annotation;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Inherited;
import java.lang.reflect.Method;/**
* Annotation在反射函数中的使用示例*/@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String[] value()default "unknown";
}/**
* Person类。它会使用MyAnnotation注解。*/
classPerson {/**
* empty()方法同时被 "@Deprecated" 和 “@MyAnnotation(value={"a","b"})”所标注
* (01) @Deprecated, 意味着empty()方法,不再被建议使用
* (02) @MyAnnotation, 意味着empty() 方法对应的MyAnnotation的value值是默认值"unknown"*/@MyAnnotation
@Deprecatedpublic voidempty(){
System.out.println("\nempty");
}/**
* sombody() 被 @MyAnnotation(value={"girl","boy"}) 所标注,
* @MyAnnotation(value={"girl","boy"}), 意味着MyAnnotation的value值是{"girl","boy"}*/@MyAnnotation(value={"girl","boy"})public void somebody(String name, intage){
System.out.println("\nsomebody:"+name+","+age);
}
}public classAnnotationTest {public static voidmain(String[] args) throws Exception {//新建Person
Person person = newPerson();//获取Person的Class实例
Class c = Person.class;//获取 somebody() 方法的Method实例
Method mSomebody = c.getMethod("somebody", new Class[]{String.class, int.class});//执行该方法
mSomebody.invoke(person, new Object[]{"lily", 18});
iteratorAnnotations(mSomebody);//获取 somebody() 方法的Method实例
Method mEmpty = c.getMethod("empty", newClass[]{});//执行该方法
mEmpty.invoke(person, newObject[]{});
iteratorAnnotations(mEmpty);
}public static voiditeratorAnnotations(Method method) {//判断 somebody() 方法是否包含MyAnnotation注解
if(method.isAnnotationPresent(MyAnnotation.class)){//获取该方法的MyAnnotation注解实例
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);//获取 myAnnotation的值,并打印出来
String[] values =myAnnotation.value();for(String str:values)
System.out.printf(str+",");
System.out.println();
}//获取方法上的所有注解,并打印出来
Annotation[] annotations =method.getAnnotations();for(Annotation annotation : annotations){
System.out.println(annotation);
}
}
}
运行结果:
somebody: lily, 18
girl, boy,
@com.skywang.annotation.MyAnnotation(value=[girl, boy])
empty
unknown,
@com.skywang.annotation.MyAnnotation(value=[unknown])
@java.lang.Deprecated()
快捷方式就是注解中定义了名为value的元素,并且在使用该注解时,如果该元素是唯一需要赋值的一个元素,那么此时无需使用key=value的语法,而只需在括号内给出value元素所需的值即可。这可以应用于任何合法类型的元素,记住,这限制了元素名必须为value,简单案例如下
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;//定义注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface IntegerVaule{int value() default 0;
String name()default "";
}//使用注解
public classQuicklyWay {//当只想给value赋值时,可以使用以下快捷方式
@IntegerVaule(20)public intage;//当name也需要赋值时必须采用key=value的方式赋值
@IntegerVaule(value = 10000,name = "MONEY")public intmoney;
}
运行时注解处理器
利用运行时注解来组装数据库SQL的构建语句的过程
/**
* 表注解*/@Target(ElementType.TYPE)//只能应用于类上
@Retention(RetentionPolicy.RUNTIME)//保存到运行时
public@interface DBTable {
String name()default "";
}/**
* 注解Integer类型的字段*/@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)public@interface SQLInteger {//该字段对应数据库表列名
String name() default "";//嵌套注解
Constraints constraint() default@Constraints;
}/**
* 注解String类型的字段*/@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)public@interface SQLString {//对应数据库表的列名
String name() default "";//列类型分配的长度,如varchar(30)的30
int value() default 0;
Constraints constraint()default@Constraints;
}/**
* 约束注解*/@Target(ElementType.FIELD)//只能应用在字段上
@Retention(RetentionPolicy.RUNTIME)public@interface Constraints {//判断是否作为主键约束
boolean primaryKey() default false;//判断是否允许为null
boolean allowNull() default false;//判断是否唯一
boolean unique() default false;
}/**
* 数据库表Member对应实例类bean*/@DBTable(name= "MEMBER")public classMember {//主键ID
@SQLString(name = "ID",value = 50, constraint =@Constraints(primaryKey= true))privateString id;
@SQLString(name= "NAME" , value = 30)privateString name;
@SQLInteger(name= "AGE")private intage;
@SQLString(name= "DESCRIPTION" ,value = 150,
constraint= @Constraints(allowNull = true))private String description;//个人描述//省略set get.....
}
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;/**
* 运行时注解处理器,构造表创建语句*/
public classTableCreator {public staticString createTableSql(String className) throws ClassNotFoundException {
Class> cl =Class.forName(className);
DBTable dbTable= cl.getAnnotation(DBTable.class);//如果没有表注解,直接返回
if(dbTable == null) {
System.out.println("No DBTable annotations in class"+className);return null;
}
String tableName=dbTable.name();//If the name is empty, use the Class name:
if(tableName.length() < 1)
tableName=cl.getName().toUpperCase();
List columnDefs = new ArrayList();//通过Class类API获取到所有成员字段
for(Field field : cl.getDeclaredFields()) {
String columnName= null;//获取字段上的注解
Annotation[] anns =field.getDeclaredAnnotations();if(anns.length < 1)continue; //Not a db table column//判断注解类型
if(anns[0] instanceof SQLInteger) {
SQLInteger sInt= (SQLInteger) anns[0];//获取字段对应列名称,如果没有就是使用字段名称替代
if(sInt.name().length() < 1)
columnName=field.getName().toUpperCase();elsecolumnName=sInt.name();//构建语句
columnDefs.add(columnName + "INT" +getConstraints(sInt.constraint()));
}//判断String类型
if(anns[0] instanceof SQLString) {
SQLString sString= (SQLString) anns[0];//Use field name if name not specified.
if(sString.name().length() < 1)
columnName=field.getName().toUpperCase();elsecolumnName=sString.name();
columnDefs.add(columnName+ "VARCHAR(" +sString.value()+ ")" +getConstraints(sString.constraint()));
}
}//数据库表构建语句
StringBuilder createCommand = newStringBuilder("CREATE TABLE" + tableName + "(");for(String columnDef : columnDefs)
createCommand.append("\n" + columnDef + ",");//Remove trailing comma
String tableCreate =createCommand.substring(0, createCommand.length() - 1) + ");";returntableCreate;
}/**
* 判断该字段是否有其他约束
* @param con
* @return*/
private staticString getConstraints(Constraints con) {
String constraints= "";if(!con.allowNull())
constraints+= "NOT NULL";if(con.primaryKey())
constraints+= "PRIMARY KEY";if(con.unique())
constraints+= "UNIQUE";returnconstraints;
}public static voidmain(String[] args) throws Exception {
String[] arg={"com.zejian.annotationdemo.Member"};for(String className : arg) {
System.out.println("Table Creation SQL for" +className+ "is :\n" +createTableSql(className));
}/**
* 输出结果:
Table Creation SQL for com.zejian.annotationdemo.Member is :
CREATE TABLE MEMBER(
ID VARCHAR(50) NOT NULL PRIMARY KEY,
NAME VARCHAR(30) NOT NULL,
AGE INT NOT NULL,
DESCRIPTION VARCHAR(150)
);*/}
}
元注解@Repeatable
元注解@Repeatable是JDK1.8新加入的,它表示在同一个位置重复相同的注解。在没有该注解前,一般是无法在同一个类型上使用相同的注解的
//Java8前无法这样使用
@FilterPath("/web/update")
@FilterPath("/web/add")public class A {}
Java8前如果是想实现类似的功能,我们需要在定义@FilterPath注解时定义一个数组元素接收多个值如下
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)public@interface FilterPath {
String [] value();
}//使用
@FilterPath({"/update","/add"})public class A { }
Java8新增了@Repeatable注解后就可以采用如下的方式定义并使用
//使用Java8新增@Repeatable原注解
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(FilterPaths.class)//参数指明接收的注解class
public@interface FilterPath {
String value();
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface FilterPaths {
FilterPath[] value();
}//使用案例
@FilterPath("/web/update")
@FilterPath("/web/add")
@FilterPath("/web/delete")class AA{ }
通过使用@Repeatable后,将使用@FilterPaths注解作为接收同一个类型上重复注解的容器,而每个@FilterPath则负责保存指定的路径串。为了处理上述的新增注解,Java8还在AnnotatedElement接口新增了getDeclaredAnnotationsByType() 和 getAnnotationsByType()两个方法并在接口给出了默认实现,在指定@Repeatable的注解时,可以通过这两个方法获取到注解相关信息。但请注意,旧版API中的getDeclaredAnnotation()和 getAnnotation()是不对@Repeatable注解的处理的(除非该注解没有在同一个声明上重复出现)。注意getDeclaredAnnotationsByType方法获取到的注解不包括父类,其实当 getAnnotationsByType()方法调用时,其内部先执行了getDeclaredAnnotationsByType方法,只有当前类不存在指定注解时,getAnnotationsByType()才会继续从其父类寻找,但请注意如果@FilterPath和@FilterPaths没有使用了@Inherited的话,仍然无法获取。下面通过代码来演示:
//使用Java8新增@Repeatable原注解
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(FilterPaths.class)public@interface FilterPath {
String value();
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface FilterPaths {
FilterPath[] value();
}
@FilterPath("/web/list")classCC { }//使用案例
@FilterPath("/web/update")
@FilterPath("/web/add")
@FilterPath("/web/delete")classAA extends CC{public static voidmain(String[] args) {
Class> clazz = AA.class;//通过getAnnotationsByType方法获取所有重复注解
FilterPath[] annotationsByType = clazz.getAnnotationsByType(FilterPath.class);
FilterPath[] annotationsByType2= clazz.getDeclaredAnnotationsByType(FilterPath.class);if (annotationsByType != null) {for(FilterPath filter : annotationsByType) {
System.out.println("1:"+filter.value());
}
}
System.out.println("-----------------");if (annotationsByType2 != null) {for(FilterPath filter : annotationsByType2) {
System.out.println("2:"+filter.value());
}
}
System.out.println("使用getAnnotation的结果:"+clazz.getAnnotation(FilterPath.class));/**
* 执行结果(当前类拥有该注解FilterPath,则不会从CC父类寻找)
1:/web/update
1:/web/add
1:/web/delete
-----------------
2:/web/update
2:/web/add
2:/web/delete
使用getAnnotation的结果:null*/}
}
View Code
执行结果来看如果当前类拥有该注解@FilterPath,则getAnnotationsByType方法不会从CC父类寻找,下面看看另外一种情况,即AA类上没有@FilterPath注解
//使用Java8新增@Repeatable原注解
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited//添加可继承元注解
@Repeatable(FilterPaths.class)public@interface FilterPath {
String value();
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited//添加可继承元注解
@interface FilterPaths {
FilterPath[] value();
}
@FilterPath("/web/list")
@FilterPath("/web/getList")classCC { }//AA上不使用@FilterPath注解,getAnnotationsByType将会从父类查询
classAA extends CC{public static voidmain(String[] args) {
Class> clazz = AA.class;//通过getAnnotationsByType方法获取所有重复注解
FilterPath[] annotationsByType = clazz.getAnnotationsByType(FilterPath.class);
FilterPath[] annotationsByType2= clazz.getDeclaredAnnotationsByType(FilterPath.class);if (annotationsByType != null) {for(FilterPath filter : annotationsByType) {
System.out.println("1:"+filter.value());
}
}
System.out.println("-----------------");if (annotationsByType2 != null) {for(FilterPath filter : annotationsByType2) {
System.out.println("2:"+filter.value());
}
}
System.out.println("使用getAnnotation的结果:"+clazz.getAnnotation(FilterPath.class));/**
* 执行结果(当前类没有@FilterPath,getAnnotationsByType方法从CC父类寻找)
1:/web/list
1:/web/getList
-----------------
使用getAnnotation的结果:null*/}
}
注意定义@FilterPath和@FilterPath时必须指明@Inherited,getAnnotationsByType方法否则依旧无法从父类获取@FilterPath注解,这是为什么呢,不妨看看getAnnotationsByType方法的实现源码:
//接口默认实现方法
default T[] getAnnotationsByType(ClassannotationClass) {//先调用getDeclaredAnnotationsByType方法
T[] result =getDeclaredAnnotationsByType(annotationClass);//判断当前类获取到的注解数组是否为0
if (result.length == 0 && this instanceof Class &&
//判断定义注解上是否使用了@Inherited元注解
AnnotationType.getInstance(annotationClass).isInherited()) { //Inheritable//从父类获取
Class> superClass = ((Class>) this).getSuperclass();if (superClass != null) {
result=superClass.getAnnotationsByType(annotationClass);
}
}returnresult;
}
View Code
参考:
http://www.cnblogs.com/skywang12345/p/3344137.html#top
https://blog.csdn.net/javazejian/article/details/71860633(推荐)