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