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中定义变量

  1. public @interface MyAnnotation {
  2. public String name();
  3. public String info();
  4. }

定义变量后, 在调用此Annotation时必须设置变量值。

  1. @MyAnnotation(name = "vince", info = "hello")
  2. public class Demo {
  3. }

通过default指定变量默认值,有了默认值在使用时可以不设值

  1. public @interface MyAnnotation {
  2. public String name() default "vince";
  3. public String info() default "hello";
  4. }

定义一个变量的数组, 接收一组参数

  1. public @interface MyAnnotation {
  2. public String[] name();
  3. }

使用时指定数组值

  1. @MyAnnotation(name = { "jack", "vince" })
  2. public class Demo {
  3. }

使用枚举限制变量取值范围

  1. public enum Color {
  2. RED, GREEN, BLUE
  3. }
  4. public @interface MyAnnotation {
  5. public Color color();
  6. }

4、 Retention和RetentionPolicy

Annotation要想决定其作用的范围, 通过@Retention指定, 而Retention指定的范围由
RetentiontPolicy决定, RetentionPolicy指定了三种范围:

范围 描述
public static final RetentionPolicy SOURCE 在java源程序中存在
public static final RetentionPolicy CLASS 在java生成的class中存在
public static final RetentionPolicy RUNTIME 在运行的时候存在
  1. @Retention(value = RetentionPolicy.RUNTIME)
  2. public @interface MyAnnotation {
  3. public String name();
  4. }

5、反射与Annotation

  1. Class<?> cls = Class.forName("com.vince.annotation.Test");
  2. Method met = cls.getMethod("setName"); // 找到setName()方法
  3. if (met.isAnnotationPresent(MyAnnotation.class)) {
  4. MyAnnotation my = (MyAnnotation) met.getAnnotation(MyAnnotation.class);
  5. String name = my.name();
  6. String info = my.info();
  7. System.out.println("name = " + name);
  8. System.out.println("info = " + info);
  9. }

6、 @Documented注解

此注解表示的是文档化, 可以在生成doc文档的时候添加注解。

  1. @Documented
  2. @Retention(value = RetentionPolicy.RUNTIME)
  3. public @interface MyAnnotation {
  4. public String name();
  5. public String info();
  6. }

可以增加一些DOC注释。

  1. /**
  2. * 这个方法是从Object类中覆写而来的
  3. */
  4. @MyAnnotation(name = "vince", info = teacher")
  5. public String toString() {
  6. return "hello";
  7. }

7、 @Target注解

@Target注解表示的是一个Annotation的使用范围, 例如: 之前定义的MyAnnotation可以在任意的位置上使用。

范围 描述
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是否允许被其子类继承下来。
示例

  1. @Inherited
  2. @Target(value = ElementType.TYPE)
  3. @Retention(value = RetentionPolicy.RUNTIME)
  4. public @interface MyAnnotation {
  5. public String name();
  6. public String info();
  7. }

Cat

  1. import java.util.Arrays;
  2. /**
  3. */
  4. @MyAnnotation(name = "bin",like = {"金鱼","鲫鱼","鲤鱼"},color = Color.GREEN)
  5. public class Cat {
  6. private String name;
  7. private int age;
  8. private Color color;
  9. private String[] like;
  10. public String[] getLike() {
  11. return like;
  12. }
  13. public void setLike(String[] like) {
  14. this.like = like;
  15. }
  16. public Color getColor() {
  17. return color;
  18. }
  19. public void setColor(Color color) {
  20. this.color = color;
  21. }
  22. public String getName() {
  23. return name;
  24. }
  25. public void setName(String name) {
  26. this.name = name;
  27. }
  28. public int getAge() {
  29. return age;
  30. }
  31. public void setAge(int age) {
  32. this.age = age;
  33. }
  34. //用于验证方法是否覆盖父类中的方法
  35. @Override
  36. public String toString() {
  37. return "Cat{" +
  38. "name='" + name + '\'' +
  39. ", age=" + age +
  40. ", color=" + color +
  41. ", like=" + Arrays.toString(like) +
  42. '}';
  43. }
  44. //用于标记方法已过时,不建议使用
  45. @Deprecated
  46. public String printInfo(){
  47. return "Cat{" +
  48. "name='" + name + '\'' +
  49. ", age=" + age +
  50. '}';
  51. }
  52. public Cat() {
  53. }
  54. public Cat(String name, int age) {
  55. this.name = name;
  56. this.age = age;
  57. }
  58. }

MyAnnotation

  1. import java.lang.annotation.*;
  2. /**
  3. * 自定义注解
  4. */
  5. //用于生成文档
  6. @Documented
  7. //表示该注解的作用范围在运行时存在
  8. @Retention(RetentionPolicy.RUNTIME)
  9. //用于表示注解的应用范围(类型,方法,属性,构造器,参数,局部变量,包,Annotation)
  10. @Target(ElementType.TYPE)
  11. @Inherited
  12. public @interface MyAnnotation {
  13. //定义变量
  14. public String name();
  15. public int age() default 2; //给变量设置默认值
  16. public String[] like();//定义一个数组变量
  17. public Color color();//定义一个枚举类型的变量
  18. }

AnnotationDemo

  1. import org.junit.Test;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. //消除警告信息
  5. @SuppressWarnings("all")
  6. public class AnnotationDemo {
  7. //反射来处理注解
  8. @Test
  9. public void test2(){
  10. Class<Cat> catClass = Cat.class;
  11. //获取类上应用的指定注解
  12. MyAnnotation annotation = catClass.getAnnotation(MyAnnotation.class);
  13. //获取注解上变量值
  14. String name = annotation.name();
  15. int age = annotation.age();
  16. Color color = annotation.color();
  17. String[] like = annotation.like();
  18. try {
  19. Cat cat = catClass.newInstance();
  20. cat.setName(name);
  21. cat.setAge(age);
  22. cat.setLike(like);
  23. cat.setColor(color);
  24. System.out.println(cat);
  25. } catch (InstantiationException e) {
  26. e.printStackTrace();
  27. } catch (IllegalAccessException e) {
  28. e.printStackTrace();
  29. }
  30. }
  31. @Test
  32. public void test1(){
  33. Cat cat = new Cat("miaomiao",3);
  34. cat.printInfo();//调用了一个已过时的方法
  35. List list = new ArrayList();
  36. list.add("vince");
  37. list.add(10);
  38. list.add(10.1f);
  39. }
  40. }

Color

  1. /**
  2. */
  3. public enum Color {
  4. RED,GREEN,YELLOW;
  5. }