从JDK5开始,Java增加对元数据的支持,也就是注解,注解与注释是有一定区别的,可以把注解理解为代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。通过注解开发人员可以在不改变原有代码和逻辑的情况下在源代码中嵌入补充信息。
注解(Annotation)可以看作是对 一个 类/方法 的一个扩展的模版,每个 类/方法 按照注解类中的规则,来为 类/方法 注解不同的参数,在用到的地方可以得到不同的 类/方法 中注解的各种参数与值
java提供了5个基本的注解,分别是@Override,@Deprecated,@SuppressWarnings,@SafeVarargs,@FunctionalInterface
限定父类重写方法: @Override,当子类重写父类方法时,子类可以加上这个注解,当子类重写父类方法时,子类可以加上这个注解。
标示已过时:@Deprecated,这个注解用于表示某个程序元素类,方法等已过时,当其他程序使用已过时的类,方法时编译器会给出警告(xxx )
抑制编译器警告:@SuppressWarnings,被该注解修饰的元素以及该元素的所有子元素取消显示编译器警告
“堆污染”警告与@SafeVarargs
函数式接口与@Functionallnterface,这个注解保证这个接口只有一个抽象方法,注意这个只能修饰接口。
函数式接口:如果接口中只有一个抽象方法(可以包含多个默认方法或多个static方法)
接口体内只能声明常量字段和抽象方法,并且被隐式声明为public,static,final。
接口里面不能有私有的方法或变量。
元注解的作用就是负责注解其他的注解,用来提供对其他annotation类型作说明。
@Retention用来修饰注解定义的,作用是被修饰的注解可以保存多久(即注解的生命周期),这个注解需要使用参数(参数可选 SOURCE,CLASS,RUNTIME)。
@Retention 源码:
package java.lang.annotation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}
@Retention注解参数是一个枚举类型,如下
package java.lang.annotation;
public enum RetentionPolicy {
SOURCE,
CLASS,
RUNTIME
}
RetentionPolicy.CLASS(默认值) 编译器把该注解记录在class文件中。当运行java程序时,JVM不可获取注解信息。
RetentionPolicy.RUNTIME编译器把该注解记录在class文件中。当运行java程序时,JVM可获取注解信息,程序可通过反射获取该注解信息
RetentionPolicy.SOURCE 该注解只保存在源代码中,编译器直接丢弃该注解。
@Target注解,用于描述注解的使用范围,即注解可以用在哪些地方(TYPE 类|接口,FIELD 字段,METHOD 方法,PARAMETER 参数…),它的使用范围也是一个枚举数组 ElementType[] value();
.
@Target注解定义源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
@Target注解的 ElementType[]参数数组源码:
package java.lang.annotation;
public enum ElementType {
TYPE,
FIELD,
METHOD,
PARAMETER,
CONSTRUCTOR,
LOCAL_VARIABLE,
ANNOTATION_TYPE,
PACKAGE,
TYPE_PARAMETER,
TYPE_USE
}
取值 | 注解使用范围 |
---|---|
METHOD | 可用于方法上 |
TYPE | 可用于类或者接口上 |
ANNOTATION_TYPE | 可用于注解类型上(被@interface修饰的类型) |
CONSTRUCTOR | 可用于构造方法上 |
FIELD | 可用于字段上 |
LOCAL_VARIABLE | 可用于局部变量上 |
PACKAGE | 用于记录java文件的package信息 |
PARAMETER | 可用于参数上 |
@Documented注解用于指定被修饰的注解类将被javadoc工具提取成文档,如果定义注解类时使用了这个注解修饰,则所有使用该注解修饰的程序员苏API文档将会包含该注解说明。
package java.lang.annotation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
@Inherited注解指定被它修饰的注解将具有继承性,即子类可以继承父类中的该注解
package java.lang.annotation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
自定义注解,需要使用@interface
来定义,使用@interface自定义注解时,自动继承java.lang.annotation.Annotation接口
。
自定义注解格式:
权限修饰符 @interface 注解名{
// 定义内容
String value() default "";
// 参数类型 参数名 默认值 ;
.....
}
String value();
表示这个注解需要提供一个String类型的参数,且其默认值为空字符串default ""
package com.robin.annotation;
import java.lang.annotation.*;
import java.lang.reflect.Method;
// 使用自定义的注解 传入参数 robin 和 23
@MyAnnotation(value = "robin", age = 23)
public class AnnoTest01 {
// 使用自定义的注解 传入参数 知更鸟 和 18
@MyAnnotation(value = "知更鸟",age = 18)
public void test01() {
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
// 通过反射来获取当前Class类对象中的注解
Class<?> cls = Class.forName("com.robin.annotation.AnnoTest01");// 获取AnnoTest01的Class类对象
MyAnnotation annotation1 = cls.getAnnotation(MyAnnotation.class);// 获取当前Class类对象的注解信息
System.out.println("作用在类上的注解:"+annotation1);// @com.robin.annotation.MyAnnotation(value=robin, age=23)
// 通过Class类对象获取Method对象
Method test01 = cls.getMethod("test01");
MyAnnotation annotation2 = test01.getAnnotation(MyAnnotation.class);
System.out.println("作用在method上的注解:"+annotation2);// @com.robin.annotation.MyAnnotation(value=知更鸟, age=18)
}
}
// 自定义内部类注解
@Target({ElementType.TYPE, ElementType.METHOD})// 作用范围为类和方法上面
@Retention(RetentionPolicy.RUNTIME)// 此注解的生命周期为RUNTIME
@interface MyAnnotation {
String value() default "";
int age() default 0;
}
祝大家除夕快乐!