注解简介,使用
英语Annotation,又被称为注释类型
是一种引用数据类型,编译之后也是.class文件
与注释的区别
注释是给程序员看的
注解是是给程序看的(@Override,@WebServlet等)
注解的目标
类(如@RestController),方法(如@Override),变量(如@Autowired)
注解的作用
其实注解就是一种给程序看的参考,或者一种标记。
注解标记的类/方法/变量上有/无这个注解,可以有两种处理方式
注解的组成部分
元注解+[修饰符列表] @interface 注解类型名+注解中定义属性
// 1. 元注解
//@Target注解用来标注,被标注的注解可以出现在哪些位置上
@Target(ElementType.METHOD)//表示被标注的注解只能标记在方法上
//@Retention用来标注,被标注的注解最终保存在什么位置上
@Retention(RntentionPolicy.SOURCE)//表示注解属性值的可见性只停留在java源文件当中
//还有RntentionPolicy.CLASS:表示该注解被保存在class文件中,但是不能被反射获取属性值
//RntentionPolicy.RUNTIME:表示该注解被保存在class文件中,并且可以被反射机制所读取属性值
// 2. [修饰符列表] @interface 注解类型名
public @interface MyAnnotation{
// 3. 注解中定义属性
String name();
String color();
int age() default 23;
}
注解的类型
1. 元注解
如果一个注解用来修饰另外一个注解,那么这个注解被称为元注解(注解注解的注解叫做元注解)
从JDK 1.5开始, Java增加了对元数据(MetaData)的支持,提供了4个标准的用来对注解类型进行注解的注解类,我们称之为 meta-annotation(元注解)
@Target 描述注解的使用范围(即:被修饰的注解可以用在什么地方)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE, // 类
/** Field declaration (includes enum constants) */
FIELD,// 变量
/** Method declaration */
METHOD,// 方法
/** Formal parameter declaration */
PARAMETER,//参数
/** Constructor declaration */
CONSTRUCTOR,//构造器
/** Local variable declaration */
LOCAL_VARIABLE,// 本地
/** Annotation type declaration */
ANNOTATION_TYPE,// 其他注解
/** Package declaration */
PACKAGE,// 包
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
@Target注解至少选一个,可以多选(因为属性是一个数组)
@Rentention 描述注解的生命周期(即:被修饰的注解被保留到何时)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
从上面的代码我们可以发现,@Retention是三选一
@Documented 会被javadoc工具动态提取成文档。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
@Inherited 允许子类继承父类中的注解。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
2. JDK自带的注解
//关于java.lang下的注解
@Deprecated//表示不鼓励程序员使用的程序元素,通常是因为它很危险或者有更好的选择
@Override
//JDK5.0新特性
//表示重写,只能注解方法,是给编译器参考的,运行阶段没有关系。
//属于标识性注解,编译器会自动检查,如果不是重写父类的方法,编译器报错
@SupperessWarnings//
@Deprecated(Since = “9”)//表示JDK9之后就过时了
- 标注的方法在非本类的main方法里面调用的时候,会被标注删除线
- 运行之后,在message里面会传递警告消息,表示已经过
注解中定义属性
如果一个注解当中有属性,调用的时候必须给该属性指定属性值,除非该属性有默认值
属性的类型可以是:
byte,short,int,long,float,double,boolean,char,String,Class,枚举类型
以及以上每一种类型的数组形式
当是数组的时候需要用大括号{}赋值,如果数组当中只有一个元素,大括号可以省略
/**
* 在注解当中可以定义属性,被此注解注解的类必须为此属性赋值
* 看着像一个方法
* 如果一个注解当中有属性,
* 调用的时候必须给该属性指定默认值,除非该属性有默认值
* @return
*/
public @interface MyAnnotation {
String name();
String color();
int age() default 23;//属性指定默认值
}
@MyAnnotation(name = "zxk",color = "blue")//age有默认值,所以不需要写出来
特殊情况value属性
//如果属性名为value,并且只有一个属性的时候,可以省略属性名和等于号不写
//属性值需要用反射机制去拿
public @interface Myannotation {
String value();
}
实例
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MyAnnotation {
String[] value();
}
@MyAnnotation("/ToRun")
public class ToRun {
@MyAnnotation("/a")
private int a;
@MyAnnotation("/run")
public void run() {
}
public static void main(String[] args) throws ClassNotFoundException {
Class clazz = Class.forName("org.leetCode.officialCode.annotation.ToRun");
MyAnnotation myAnnotation = (MyAnnotation) clazz.getDeclaredAnnotation(MyAnnotation.class);
System.out.println(myAnnotation.value()[0]);
}
}