注解
简介
注解是一系列元数据,它提供数据用来解释程序代码,但是注解并非是所解释的代码本身的一部分。注解对于代码的运行效果没有直接影响。
注解有许多用处,主要如下:
- 提供信息给编译器: 编译器可以利用注解来探测错误和警告信息
- 编译阶段时的处理: 软件工具可以用来利用注解信息来生成代码、Html文档或者做其它相应处理。
- 运行时的处理: 某些注解可以在程序运行的时候接受代码的提取值得注意的是,注解不是代码本身的一部分。
注解好比一个标签,给某个类、方法、字段等添加注解就相当于贴上了一个标签,在生活中贴标签的目的一般是为了方便对物体进行分类;在代码中也是如此,在代码上面添加一个注解后,该代码就被赋予了改注解具有的功能。其实仅仅是给代码做了标记,实现的过程是编写了一个处理注解的程序,该程序会扫描目标代码中的注解,对有注解的代码做一些特有的操作,在这个过程中应用到了Java的反射进行扩展功能的实现。
(反射就是程序在运行时,可以根据类的全限定名称,动态地加载该类,创建对象,并可以调用该对象中地任意属性和方法。)
通过反射,可以取得一个方法上声明的注解中的全部内容。
元注解
一种基本注解,可以注解到注解上的注解。
元注解有 6 种。
Java 1.5:
@Retention、@Documented、@Target、@Inherited
Java 1.8 新增:
@Repeatable、@Native
@Retention
意为保留期,解释说明注解的存活时间。
取值:
RetentionPolicy.SOURCE :注解只在源码阶段保留,编译时会忽略
RetentionPolicy.CLASS : 注解只保留到编译阶段,不会被加载到JVM
RetentionPolicy.RUNTIME : 注解可保留到程序运行的时候。
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
}
@Documented
作用是将注解中的元素包含到 javaDoc中
@Target
意为目标,作用是指定注解使用的地方(方法、类、属性等)
取值:
ElementType.ANNOTATION_TYPE 给一个注解进行注解
ElementType.CONSTRUCTOR 给构造方法进行注解
ElementType.FIELD 给属性进行注解
ElementType.LOCAL_VARIABLE 给局部变量进行注解
ElementType.METHOD 给方法进行注解
ElementType.PACKAGE 给一个包进行注解
ElementType.PARAMETER 给一个方法内的参数进行注解
ElementType.TYPE 给一个类型进行注解,比如类、接口、枚举
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
}
@Inherited
意为继承,被该注解注解了的注解,若注解到某个类上,则该类的子类也就自动继承了父类的注解
@Repeatable
可重复,表示可以在同一个地方重复使用一个注解。
@Native
指示可以从本机代码引用定义常量值的字段。注释可以用作生成本机头文件的工具的提示,以确定是否需要头文件,如果需要,它应该包含哪些声明。一般在框架中用的较多,了解即可
注意:
1、Annotation是 JDK1.5后引入的,主要是使用注释的形式进行开发,通常配合反射使用。
2、Annotation要想配合反射机制,必须设置 @Retention(valeu = RetentionPolicy.RUNTIME)
3、如果一个Annotation希望被使用类的子类继承,须使用 @Inherited 注解
注解的属性
注解的属性也就是成员变量,并且注解只有变量,没有方法。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DemoAnno {
int num () default 1;
String color ();
}
@DemoAnno(color = "red", num = 2)
public Apple(){
}
1、注解中的成员变量书写方式如上。(常量后添加圆括号)
2、成员变量类型必须为8中基本类型,以及类、接口、接口、以及它们的数组。
3、使用时需要给变量进行赋值,有默认值得变量重新赋值会覆盖默认值。多个赋值之间用逗号相隔。
4、若注解只有一个属性,则在使用时可进行简写,例如 @DemoAnno(“red”)。
5、若注解中没有任属性,可简写,例如 @DemoAnno
Java预置注解
- @Deprecated 用于标记已过时并不推荐使用得元素,在开发中调用某个带有该注解得方法时,编译器会提示,提示方式时在调用的方法上画一条直线,表示已弃用。
- @Override 提示子类复写父类方法,也可检查复写方法时方法名及参数是否正确。
- @SuppressWarnings 阻止编译器的警告。
- @SafeVarargs
- @FunctionalInterface Java1.8引入的函数时接口注解。函数式接口就是一个具有一个方法的普通接口。例如最常见的Runable接口就使用到了该注解。
注解功能的实现
注解通过反射获取,可通过Class类的方法有获取注解/判断是否应用某注解等注解相关的方法。
通过反射获取到注解对象,再通过操作注解对象,调用它们自己的属性方法。
属性、方法等注解类似,先使用反射获取到属性或方法,再去获取其上面的注解。
更多方法查看API
@DemoAnno(num = 2, str = "str2")
public class AnnotationDemo {
public static void main(String[] args) {
boolean annotation = AnnotationDemo.class.isAnnotationPresent(DemoAnno.class);
if(annotation){
DemoAnno annotation1 = AnnotationDemo.class.getAnnotation(DemoAnno.class);
System.out.println(annotation1.num());
System.out.println(annotation1.str());
}
}
}
------------------------------------------------
结果:
2
str2
总结:
链接:Java 反射