1注释的定义和用途
1.1官方说明
An annotation is a form of metadata,that can be added to Java source code。
Classes、methods、variables、parametersandpackagesmaybeannotated。
annotationshavenodirecteffectontheoperationofthecodetheyannotate。
注释是可以添加到java代码中的元数据,它是类似于类、接口、数组和枚举的java数据类型
类、方法、变量、参数和包可以用注释限定
注释不会直接影响限定的代码
1.2用途
Annotations have a number of uses,among them:
informationforthecomplier-annotationscanbeusedbythecompilertodetecterrorsorsuppresswarnings。
compiler-timeanddeployment-time processing-softwaretoolscanprocessannotationtogeneratecode,XML files,andsoff
运行时处理- someannotationsareavailabletobeexaminedatruntime。
向编译器提供信息:编译器可以使用注释来检测错误和抑制警告
编译和部署时的处理:软件工具可以处理注释信息并生成代码、XML文件等
运行时处理:有些注释可以在运行时检查
2使用自定义注释
注释是标记程序代码中的关键点(类、方法、变量、参数和包)的标记,程序可以在编译或运行时检测到这些点并执行特殊操作
基本步骤
定义注释
设置注释并标记所需的代码
分析注释在编译或运行时检测标记并执行特殊操作
2.1注释的定义
1 //@CherryAnnotation仅限于方法,在运行时有效
2 @ retention (retention policy.runtime )3@target ) value={elementtype.method} )4public @ interfacecherryanotion
5公共字符串name (; 6 int age ) ) default 18; 7 int[] array (; 8 }
声明注释类型:使用关键字@interface时,在基本实现中,所有定义的注释都会自动继承Java.lang.annotation.annotation接口。
注释性实现部分:只能定义注释性元素
注释元素的使用注意事项:
a .访问修饰符必须是公共的,不写的默认值是公共的;
b .该元素的类型只能是基本数据类型、字符串、类、枚举类型、注释类型和数组;
c .元素名称一般定义为名词,如果注释中只有一个元素,则名称可以为value
d.) )是特殊语法,不能定义参数
e.default是默认值,必须与定义类型匹配
f .如果没有默认值,这意味着以后使用注释时必须为类型更改元素赋值
元注释:修饰注释的注释
@Target注释用于限制可以应用特定自定义注释的Java元素。 使用枚举类型定义如下:
1公共枚举类型{2/* *类、接口(包括注释类型)或枚举的声明) /
3类型,4
5 /**属性的声明*/
6个字段,7
8 /**方法声明*
9方法,10
11 /**方法格式参数声明*
12参数,13
14 /**构建方法声明*
15构造器,16
17 /**局部变量宣言*/
18 LOCAL_VARIABLE,19
20 /**评论类型声明*
21 ANNOTATION_TYPE,22
23 /**包声明*
24包25 }
@Retention注释用于限定自定义注释的生命力。
评论的生命周期有三个阶段。 1、Java源文件阶段; 2、编译成class文件阶段3、运行时间表
段。RetentionPolicy枚举类型1 public enumRetentionPolicy {2 /**
3 * Annotations are to be discarded by the compiler.4 * (注解将被编译器忽略掉)5 * 将被限定在Java源文件中,这个注解即不会参与编译也不会在运行期起任何作用,就和注释是一样的效果,只能被阅读Java文件的人看到;6 */
7 SOURCE,8
9 /**
10 * Annotations are to be recorded in the class file by the compiler11 * but need not be retained by the VM at run time. This is the default12 * behavior.13 * (注解将被编译器记录在class文件中,但在运行时不会被虚拟机保留,这是一个默认的行为)14 * 将被编译到Class文件中,编译器可以在编译时根据注解做一些处理动作,但是运行时JVM(Java虚拟机)会忽略它,我们在运行期也不能读取到;15 */
16 CLASS,17
18 /**
19 * Annotations are to be recorded in the class file by the compiler and20 * retained by the VM at run time, so they may be read reflectively.21 * (注解将被编译器记录在class文件中,而且在运行时会被虚拟机保留,因此它们能通过反射被读取到)22 * 注解可以在运行期的加载阶段被加载到Class对象中。在程序运行阶段,我们可以通过反射得到这个注解,并通过判断是否有这个注解或这个注解中属性的值,23 * 从而执行不同的程序代码段。我们实际开发中的自定义注解几乎都是使用的RetentionPolicy.RUNTIME;24 *@seejava.lang.reflect.AnnotatedElement25 */
26 RUNTIME27 }
@Documented注解,是被用来指定自定义注解是否能随着被定义的java文件生成到JavaDoc文档当中。
@Inherited注解,是指定某个自定义注解如果写在了父类的声明部分,那么子类的声明部分也能自动拥有该注解。@Inherited注解只对那些@Target被定义为ElementType.TYPE的自定义注解起作用。
2.2 配置注解 把标记打在需要用到的代码中
1 public classStudent {2 @CherryAnnotation(name = "cherry-peng",age = 23,score = {99,66,77})3 public void study(inttimes){4 for(int i = 0; i < times; i++){5 System.out.println("Good Good Study, Day Day Up!");6 }7 }8 }
在定义的注解中,有些注解类型元素没有默认值,使用的时候需要在标记名后面加上(),并以“元素名1=元素值1,元素名2=元素值=2”的形式为元素赋值。(原有默认的会被覆盖)
2.3 解析注解 在编译时或运行时检测到标记,并进行特殊操作
只有当注解的保持力处于运行阶段,即使用@Retention(RetentionPolicy.RUNTIME)修饰注解时,才能在JVM运行时,检测到注解,并进行一系列特殊操作。
反射操作获取注解
public classTestAnnotation {public static voidmain(String[] args){try{//获取Student的Class对象
Class stuClass = Class.forName("pojos.Student");//说明一下,这里形参不能写成Integer.class,应写为int.class
Method stuMethod = stuClass.getMethod("study",int.class);//判断该元素上是否配置有某个指定的注解
if(stuMethod.isAnnotationPresent(CherryAnnotation.class)){
System.out.println("Student类上配置了CherryAnnotation注解!");//获取该元素上指定类型的注解
CherryAnnotation cherryAnnotation = stuMethod.getAnnotation(CherryAnnotation.class);
System.out.println("name: " + cherryAnnotation.name() + ", age: " +cherryAnnotation.age()+ ", score: " + cherryAnnotation.score()[0]);
}else{
System.out.println("Student类上没有配置CherryAnnotation注解!");
}
}catch(ClassNotFoundException e) {
e.printStackTrace();
}catch(NoSuchMethodException e) {
e.printStackTrace();
}
}
}//getAnnotations(),该方法可以获得该对象身上配置的所有的注解,返回Annotation类型数组
特殊语法
1.如果注解本身没有注解类型元素,在使用注解的时候可以省略(),直接写为:@注解名,它和标准语法@注解名()等效
1 @Retention(RetentionPolicy.RUNTIME)2 @Target(value ={ElementType.TYPE})3 @Documented4 public @interfaceFirstAnnotation {5 }6 ------------------------------------
7 //等效于@FirstAnnotation()
8 @FirstAnnotation9 public classJavaBean{10 //省略实现部分
11 }
2.如果注解本本身只有一个注解类型元素,而且命名为value,在使用注解的时候可以直接使用:@注解名(注解值),其等效于:@注解名(value = 注解值)
@Retention(RetentionPolicy.RUNTIME)
@Target(value={ElementType.TYPE})
@Documentedpublic @interfaceSecondAnnotation {
String value();
}------------------------------------
//等效于@ SecondAnnotation(value = "this is second annotation")
@SecondAnnotation("this is annotation")public classJavaBean{//省略实现部分
}
3.如果某个注解类型元素是一个数组类型,在使用时又只需要填入一个值的情况,在使用注解时可以直接写为:@注解名(类型名 = 类型值),它和标准写法:@注解名(类型名 = {类型值})等效
@Retention(RetentionPolicy.RUNTIME)
@Target(value={ElementType.TYPE})
@Documentedpublic @interfaceThirdAnnotation {
String[] name();
}--------------------------------------
//等效于@ ThirdAnnotation(name = {"this is third annotation"})
@ ThirdAnnotation(name = "this is third annotation")public classJavaBean{//省略实现部分
}
4.如果一个注解的@Target是定义为Element.PACKAGE,这个注解是配置在package-info.java中的,而不能直接在某个类的package代码上面配置。
Java 定义了一套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。
作用在代码的注解是
1 @Override -检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。2 @Deprecated -标记过时方法。如果使用该方法,会报编译警告。3 @SuppressWarnings -指示编译器去忽略注解中声明的警告。4 作用在其他注解的注解(或者说 元注解)是:5 @Retention -标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。6 @Documented -标记这些注解是否包含在用户文档中。7 @Target -标记这个注解应该是哪种 Java 成员。8 @Inherited -标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)9 从 Java 7 开始,额外添加了 3个注解:10 @SafeVarargs - Java 7开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。11 @FunctionalInterface - Java 8开始支持,标识一个匿名函数或函数式接口。12 @Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。