注解是一种能被添加到java代码中的元数据(python中的函数装饰器),类、方法、参数、变量和包都可以用注解来修饰。用来定义一个类、属性或者一些方法,以便程序能被捕译处理。相当于一个说明文件,告诉应用程序某个被注解的类或者属性是什么,要怎么处理。对被修饰的代码本身没有直接影响。
使用范围:
1)为编译器提供信息:注解能被编译器检测到错误或抑制警告。
2)编译时和部署时的处理: 软件工具能处理注解信息从而生成代码,XML文件等等。
3)运行时的处理:有些注解在运行时能被检测到。
自定义注解的步骤:
第一步:定义注解
第二步:配置注解
第三步:解析注解
1.最基本的注解定义
public @interface MyAnnotation{
public String name();
int age();
String sex() default "女";
}
在自定义注解中,其实现部分只能定义注解类型元素!
2.常用的元注解
元注解:专门修饰注解的注解
@Target
@Target是专门用来限定某个自定义注解(如上面的@interface MyAnnotation)能够被应用在哪些Java元素上面的。枚举类型。
因此,我们可以在使用@Target时指定注解的使用范围
//@MyAnnotation被限定只能使用在(类、接口)TYPE或(方法)METHOD上面
@Target(value = {ElementType.METHOD,ElementType.TYPE})
public @interface MyAnnotation {
public String name();
int age();
String sex() default "女";
}
@Retention注解,用来修饰自定义注解的生命力。
a.如果一个注解被定义为RetentionPolicy.SOURCE,则它将被限定在Java源文件中,那么这个注解即不会参与编译也不会在运行期起任何作用,这个注解就和一个注释是一样的效果,只能被阅读Java文件的人看到;
b.如果一个注解被定义为RetentionPolicy.CLASS,则它将被编译到Class文件中,那么编译器可以在编译时根据注解做一些处理动作,但是运行时JVM(Java虚拟机)会忽略它,我们在运行期也不能读取到,是默认的;
c.如果一个注解被定义为RetentionPolicy.RUNTIME,那么这个注解可以在运行期的加载阶段被加载到Class对象中。那么在程序运行阶段,我们可以通过反射得到这个注解,并通过判断是否有这个注解或这个注解中属性的值,从而执行不同的程序代码段。我们实际开发中的自定义注解几乎都是使用的RetentionPolicy.RUNTIME。
使用此注解修饰自定义注解生命力的示例如下:
//设置注解的生命力在运行期
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
public String name();
int age();
String sex() default "女";
}
@Inherited注解,是指定某个自定义注解如果写在了父类的声明部分,那么子类(继承关系)的声明部分也能自动拥有该注解。该注解只对@Target被定义为ElementType.TYPE的自定义注解起作用。
自定义注解举例
第一步:自定义的注解如下
package com.example.demo.config;
import java.lang.annotation.*;
@Target(value={ElementType.METHOD}) //只能被使用在方法上面
@Retention(RetentionPolicy.RUNTIME)//设置注解的生命力在运行期,那么这个注解可以在运行期的加载阶段被加载到Class对象中。那么在程序运行阶段,我们可以通过反射得到这个注解,并通过判断是否有这个注解或这个注解中属性的值,从而执行不同的程序代码段
@Documented
public @interface MyAnnotation {
public String name();
int age();
String sex() default "女";
String[] hobby();
}
第二步:创建一个类,新建方法使用该注解
package com.example.demo.controller;
import com.example.demo.config.MyAnnotation
public class UserController{
@MyAnnotation(name = "张三",age = 18, hobby ={"跑步","打游戏"})//注解里面的字段
public String get(){
return "Hello Annotation";
}
}
第三步:利用反射获取注解。创建一个类,代码如下:
package com.example.demo.test;
import com.example.demo.config.MyAnnotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) {
try {
//获取Class对象
Class mylass = Class.forName("com.example.demo.controller.UserController");
//获得该对象身上配置的所有的注解
Annotation[] annotations = mylass.getAnnotations();
System.out.println(annotations.toString());
//获取里面的一个方法
Method method = mylass.getMethod("get");
//判断该元素上是否配置有某个指定的注解
if(method.isAnnotationPresent(MyAnnotation.class)){
System.out.println("UserController类的get方法上配置了MyAnnotation注解!");
//获取该元素上指定类型的注解
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
System.out.println("name: " + myAnnotation.name() + ", age: " + myAnnotation.age()
+ ",sex:"+myAnnotation.sex()+", hobby: " + myAnnotation.hobby()[0]);
}else{
System.out.println("UserController类的get方法上没有配置MyAnnotation注解!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
打印结果