注解
元数据(Metadata)的意思是“数据的数据”,作用是提供数据本身的信息。注解就是代码的元数据,是描述代码的代码。
注解和注释是两个完全不同的概念,注释会被编译器忽略,而编译器会检查注解的错误。例如,@Override重写注解的方法如果在父类中并不存在,编译则无法通过。
**注解的分类:** 1、 按照运行机制分: 源码注解:注解只在源码中存在,编译成.class文件就不存在了; 编译时注解:注解在源码和.class文件中都存在; 运行时注解:在运行阶段还起作用,甚至会影响运行逻辑的注解; **2、按照来源分:** JDK注解 第三方注解 自定义注解 元注解
元注解:
元注解(Meta-Annotations)的意思是(“注解的注解”),作用是给注解做说明,定义注解的生命周期、作用范围等。
java中的元注解有@Documented、@Retention、@Target、@Inherit、@Repeatable,这些元注解在定义注解时候使用
1、@Documented:表示将该注解信息添加在javadoc中
2、@Retention:定义该注解的生命周期,即描述标注信息保留到什么时候。
3、@Target:描述可以为哪些程序组件添加此注解。
4、@Inherited:指示该注解类型是自动继承的。
5、@Repeatable:指示该注解类型是可重复的。
Retention属性
参数 | 描述 |
RetentionPolicy.SOURCE | 在源码中保留,在编译阶段丢弃,生命周期最短 |
RetentionPolicy.CLASS | 在.class文件中保留,在类加载时丢弃 |
RetentionPolicy.RUNTIME | 运行时有效,始终不丢弃,生命周期最长 |
@Target
参数 | 描述 |
ElementType.TYPE | 类、接口、枚举类型、注解类型 |
ElementType.FIELD | 域变量 |
ElementType.METHOD | 方法 |
ElementType.PARAMETER | 参数 |
ElementType.CONSTRUCTOR | 构造方法 |
ElementType.LOCAL_VRIABLE | 局部变量 |
ElementType.ANNOTATION_TYPE | 另外一个注解 |
ElementType.PACKAGE | 包 |
自定义注解:
注解的本质是一个接口,它直接或间接继承Annotation接口。简单的注解定义一般形式如下:
public @interface MyAnnotation{
//注解的定义语句
}
上面的注解没有用任何元注解来注解。在使用@interface自定义注解时,会自动继承java.lang.annotation.Annotation接口。
自定义注解中的每个方法实际上声明了一个配置参数,方法名即参数名,方法的返回值类型就是参数的类型。用default来声明参数的默认值。
自定义注解需要注意以下两点
1、方法的返回值类型包括八种基本数据类型、String类型、Class类型、enum类型、Annotation类型和所列类型的数组。
2、只能用public或缺省(default)两种访问权限修饰。
自定义注解语法
/**
* 元注解
*/
//注解的作用域
@Target({ElementType.METHOD,ElementType.TYPE})
//注解的生命周期
@Retention(RetentionPolicy.RUNTIME)
//允许子类继承,只有用在类上时才会生效,对接口无效
@Inherited
//生成javadoc时会包含注解
@Documented
public @interface Test {
/**
* 1.成员类型是受限制的,合法的类型包括:
* 原始类型及String,Class,Annotation,Enumeration;
* 2.如果注解只有一个成员,则成员名必须取名为value(),在使用
* 时可以省略成员名和赋值的“=”号;
* 3.注解类可以没有成员,没有成员的注解称为标识注解;
*/
//value();
//成员以无参无异常的方式声明
String desc();
String author();
//可以用default为成员指定一个默认值
int age() default 18;
}
使用自定义注解
使用注解的语法:@<注解名>(成员=值,成员=值,……)
@Test(desc="",author="",age=18)
public void demo(){
}
解析注解
获得类上的注解
//获得对象类类型
Class c = Demo.class;
//获得类上面的注解
boolean b = c.isAnnotationPresent(Test.class);
if(b){
//获得注解对象
Test t = (Test) c.getAnnotation(Test.class);
//打印注解成员的值
System.out.println(t.desc());
System.out.println(t.author());
System.out.println(t.age());
}
获得方法上的注解
//获得类中的所有方法对象
Method[] ms = c.getMethods();
for (Method m : ms) {
boolean is = m.isAnnotationPresent(Test.class);
if(is){
//获得方法上的注解
Test mt = m.getAnnotation(Test.class);
System.out.println(mt.desc());
System.out.println(mt.author());
System.out.println(mt.age());
}
}
方法二
//方法二
for (Method m : ms) {
Annotation[] as = m.getAnnotations();
for (Annotation a : as) {
if(a instanceof Test){
Test t = (Test) a;
System.out.println(t.desc());
System.out.println(t.author());
System.out.println(t.age());
}
}
}
常用注解:
1、@Override注解,用来标识重写父类的方法。
2、@Deprecated注解,用来表示过时的类或方法,建议不再使用该类或该方法
3、@SuppressWarnings注解,用来阻止编译器的某些警告