1、认识Annotation
JDK1.5开始,Java增加了对元数据(即类的组成单元数据)的支持,也就是(Annotation)注解,他是代码里做的特殊标记,这些标记可以在编译,类加载,运行时在不改变原有逻辑的情况下,被读取,并执行相应的处理,通过使 Annotation,程序员可以在源文件中嵌入一些补充的信息。代码分析工具,开发工具和部署工具可以通过这些补充信息进行验证或者进行部署。Annotation类似于修饰符一样被使用,可以用于包,类,构造方法,方法,成员变量,参数,局部变量的声明。
注意:
Annotation是一个接口
java.lang.Annotation接口.
2、系统定义的Annotation
在JDK 1.5之后,在系统中提供了三个Annotation,分别是:@Override、@Deprecated、@SuppressWarnings。
-
@Override
表示当前的方法定义将覆盖超类中的方法。如果你不小心拼写错误,或者方法签名对不上被覆盖的方法,编译器就会发出错误提示。 -
@Deprecated
表示的是一个类或方法已经不再建议继续使用了,标记为已过时。 -
@SuppressWarnings
表示关闭不当的编译器警告信息。
@SuppressWarnings(“unchecked”)//未检查的转化,如集合没有指定类型
@SuppressWarnings(“unused”) //未使用的变量
@SuppressWarnings(“resource”) //有泛型未指定类型
@SuppressWarnings(“path”) //在类路径,原文件路径中有不存在的路径
@SuppressWarnings(“deprecation”) //使用了某些不赞成使用的类和方法
@SuppressWarnings(“fallthrough”) //switch语句执行到底没有break关键字
@SuppressWarnings(“serial”)//某类实现Serializable 但是没有定义serialVersionUID 这个需要但是不必须的字段
@SuppressWarnings(“rawtypes”) //没有传递带有泛型的参数
@SuppressWarnings(“all”) //全部类型的警告
3、自定义Annotation
注解应用需要三个步骤:
- (1)编写注解
- (2)在类上应用注解
- (3)对应用了注解的类进行反射操作的类
自定义Annotation的语法如下:
访问控制权限 @interface Annotation名称{}
例如:
public @interface MyAnnotation {}
在Annotation中定义变量
public @interface MyAnnotation {
public String name();
public String info();
}
定义变量后,在调用此Annotation时必须设置变量值。
@MyAnnotation(name = “vince", info = “hello")
public class Demo {
}
通过default指定变量默认值,
有了默认值在使用时可以不设值
public @interface MyAnnotation {
public String name() default “vince";
public String info() default “hello";
}
定义一个变量的数组,接收一组参数
public @interface MyAnnotation {
public String[] name();
}
使用时指定数组值
@MyAnnotation(name = { “jack", “vince" })
public class Demo {
}
使用枚举限制变量取值范围
public enum Color {
RED, GREEN, BLUE
}
public @interface MyAnnotation {
public Color color();
}
4、Retention和RetentionPolicy
Annotation要想决定其作用的范围,通过@Retention指定,而Retention指定的范围由RetentiontPolicy决定,RetentionPolicy指定了三种范围:
范围 | 描述 |
---|---|
public static final RetentionPolicy SOURCE | 在java源程序中存在, 编译时检查,提供给编译器使用,如,@override |
public static final RetentionPolicy CLASS | 在java生成的class中存在 |
public static final RetentionPolicy RUNTIME | 在java运行的时候存在 |
示例:
@Retention(value = RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
public String name();
}
5、反射与Annotation
一个Annotation真正起作用,必须结合反射机制,在反射中提供了以下的操作方法:java.lang.reflect.AccessibleObject
方法名称 | 描述 |
---|---|
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) | 判断是否是指定的Annotation |
public Annotation[] getAnnotations() | 得到全部的Annotation |
示例:
Class<?> cls = Class.forName(“com.vince.annotation.Test");
Method met = cls.getMethod(“setName"); // 找到setName()方法
if (met.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation my = (MyAnnotation) met.getAnnotation(MyAnnotation.class);
String name = my.name();
String info = my.info();
System.out.println("name = " + name);
System.out.println("info = " + info);
}
6、@Documented注解
此注解表示的是文档化,可以在生成doc文档的时候添加注解。
@Documented
@Retention(value = RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
public String name();
public String info();
}
可以增加一些DOC注释。
/**
* 这个方法是从Object类中覆写而来的
*/
@MyAnnotation(name = “vince", info = “teacher")
public String toString() {
return "hello";
}
7、@Target注解
@Target注解表示的是一个Annotation的使用范围,不指定就是全范围适用。
范围 | 描述 |
---|---|
public static final ElementType TYPE | 只能在类或接口或枚举上使用 |
public static final ElementType FIELD | 在成员变量使用 |
public static final ElementType METHOD | 在方法中使用 |
public static final ElementType PARAMETER | 在参数上使用 |
public static final ElementType CONSTRUCTOR | 在构造中使用 |
public static final ElementType LOCAL_VARIABLE | 局部变量上使用 |
public static final ElementType ANNOTATION_TYPE | 只能在Annotation中使用 |
public static final ElementType PACKAGE | 只能在包中使用 |
8、@Inherited注解
@Inherited表示一个Annotation是否允许被其子类继承下来。
示例:
@Inherited
@Target(value = ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
public String name();
public String info();
}
使用时允许被其子类所继承。
package cn.saul.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义注解
* @author moushuai
*
*/
//注解的使用范围
@Target(value = {ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR})
//作用范围
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
public String name();
public int id();
public int age() default 2; //给变量设置默认值
public String[] likes(); //定义一个数组变量
public Color color(); //定义一个枚举变量
}
package cn.saul.annotation;
public enum Color {
RED,
BLUE,
WHITE
}
package cn.saul.annotation;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Setter
@Getter
@ToString
@MyAnnotation(name = "huahua", id=123, likes = {"fish","meat"},color = Color.WHITE)
public class Cat {
private String name;
private int id;
private int age;
private String[] likes;
private Color color;
public Cat(String name, int id, int age) {
super();
this.name = name;
this.id = id;
this.age = age;
}
public Cat() {
super();
}
}
package cn.saul.annotation;
import java.lang.annotation.Annotation;
import org.junit.Test;
public class MyAnnotationTest {
private Cat cat;
//反射处理注解
@Test
public void test() {
Class<?> class1 = Cat.class;
//获取类上应用的所有注解
Annotation[] annotations = class1.getAnnotations();
MyAnnotation myAnnotation = null;
for (int i = 0; i < annotations.length; i++) {
if (annotations[i].annotationType().getName().equals("cn.saul.annotation.MyAnnotation")) {
myAnnotation = (MyAnnotation) annotations[i];
}
}
//获取注解上的变量
String name = myAnnotation.name();
int age = myAnnotation.age();
Color color = myAnnotation.color();
String[] likes = myAnnotation.likes();
int id = myAnnotation.id();
try {
cat = (Cat) class1.newInstance();
cat.setAge(age);
cat.setColor(color);
cat.setId(id);
cat.setLikes(likes);
cat.setName(name);
System.out.println(cat);
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
}