java中Annotation注解的定义与使用

时间:2022-12-22 20:14:32

注解也称作元数据,它为我们在源码中添加信息提供了一种形式化的方法,供我们在需要的时候读取有用的信息。

java中内置了三种注解:

注解 使用方法
@Overide 表示当前的方法的定义将覆盖超类中的方法的定义
@Deprecated 编译器将会发警告,表示这个方法或者成员变量将会在之后的版本中放弃
@SuppressWarnnings 关闭不当的编译器警告信息


那么我们应该怎么定义自己的注解类型呢?自定义注解的语法同自定义接口的语法格式类似:

@Target(ElementTYpe.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test{
public String values();
public int numberId();
public String descrption() default "no description";
}

同定义接口的格式相比,定义注解有下面几个不同的点:

1. 定义注解需要使用@interface。
2. 注解中的元素都是以类似方法的形式定义的。
3. 这些元素可以设置默认值,以default后跟的值表示默认值。
4. 注解是不可以继承的,但是可以对同一个元素使用多个注解。

注解中的元素的类型是有限的,固定为下面几种:

  • 所有的基本类型(int、foat、boolean等)
  • String
  • Class
  • enum
  • Annotation
  • 以上类型的数组

除了以上的基本语法外,定义注解还需要四种元注解来修饰,所谓的元注解也就是用来修饰我们自定义的注解。在java种定义了4种元注解,如下:

类型 说明
@Target 表示该注解可以用在什么地方,可能的ElementType的参数包括:
- CONSTRUCTOR:构造器的声明
- FIELD:域声明(包括enum实例)
- LOCAL_VARIABLE:局部变量的声明
- METHOD:方法声明
- PACKAGE:包声明
- TYPE:类、接口(包括注解类型)或者enum声明
- PARAMETER:参数声明
@Retention 表示需要在什么级别上保留注解信息。可选的RetentionPolicy参数包括:
- SOURCE:注解将被编译器丢弃
- CLASS:注解在class文件上可用,但是会被JVM丢弃
- RUNTIME:VM将在运行期间保留注解
@Documented 将此注解保留在javadoc中
@Inherited 允许子类继承父类中的注解


注解的处理才是重点,如果注解没有处理,那么本质上注释没有差别,注解的处理的核心就是反射机制,通过反射获取注解中的信息

下面通过一个简单例子说面注解的处理,定义一个注解如下:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Person {
public String name();
public String[] children();
}

有一个简单的javabean如下:

public class Parent {
private int id;
private String name;
private int age;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}

那么对于标注了@Person的成员变量,我们就可以通过注解获取信息了

public class PersonClient {

@Person(name = "zhangsan", children = {"lilei", "hanmeimei", "xiaoyu"})
public Parent p = new Parent();

public static void main(String[] args) throws Exception{
PersonClient client = new PersonClient();
Class clz = client.getClass();
Field field = clz.getDeclaredField("p");
Person ap = field.getAnnotation(Person.class);
if(ap != null){
System.out.println("my name is:"+ap.name()+", I have children named " + Arrays.toString(ap.children()));
}
}
}

打印结果如下:

my name is:zhangsan, I have children named [lilei, hanmeimei, xiaoyu]

在补充两点:
1. 注解的非基本类型的值都不能是null,不管是设置的默认值,还是在使用中设置的值
2. 如果注解中某个元素的值是注解,那么他的默认的语法格式如下:
Constraints constraints() @Constraints;
在使用中如果更改元素的值的话应该如下设置:
constraints =@Constraints(value=”zhangsan”)