七、元注解
J2SE5.0版本在 java.lang.annotation提供了四种元注解,专门注解其他的注解:
@Documented:注解是否将包含在JavaDoc中
@Retention :什么时候使用该注解
@Target :注解用于什么地方
@Inherited :是否允许子类继承该注解
7.1 @Documented:一个简单的Annotations标记注解,表示是否将注解信息添加到Java文档中。
7.2 @Retention:定义该注解的生命周期, 其中Retention保持、保留的意思,RetentionPolicy:保持、保留政策、方针、策略。
在Java编译器编译时,它会识别在源代码里添加的注解是否还会保留,这就是RetentionPolicy。下面是Java定义的RetentionPolicy枚举:
编译器的处理有三种策略:
将注解保留在编译后的类文件中,并在第一次加载类时读取它;RUNTIME
将注解保留在编译后的类文件中,但是在运行时忽略它;CLASS
按照规定使用注解,但是并不将它保留到编译后的类文件中;SOURCE
Java源码:
public enum RetentionPolicy {
SOURCE,// 此类型会被编译器丢弃
CLASS,// 此类型注解会保留在class文件中,但JVM会忽略它
RUNTIME// 此类型注解会保留在class文件中,JVM会读取它
}
1、RetentionPolicy.SOURCE :保留注解到java源文件阶段,即在编译阶段丢弃,这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码,像@Override, @SuppressWarnings都属于这类注解。
2、RetentionPolicy.CLASS:在类加载的时候丢弃,在字节码文件的处理中有用,这是注解默认的方式。
3、RetentionPolicy.RUNTIME:始终不会丢弃,运行期也保留该注解,保留注解到运行时阶段即内存中的字节码,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。
7.3 @Target:表示该注解用于什么地方,如果不明确指出,该注解可以放在任何地方。 Java源码:
public enum ElementType {
TYPE,// 用于类,接口,枚举但不能是注解
FIELD,//字段上,包括枚举值
METHOD,//方法,不包括构造方法
PARAMETER,// 方法的参数
CONSTRUCTOR,// 构造方法
LOCAL_VARIABLE,// 本地变量或catch语句
ANNOTATION_TYPE,//注解类型(无数据)
PACKAGE//Java包
}
7.4 @Inherited –定义该注释和子类的关系
@Inherited元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
八、自定义注解
使用@interface自定义注解,语法格式如下:public @interface 注解名 {定义体},它自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口,
@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型,这种类型包括:
1、所有基本数据类型(int,float,boolean,byte,double,char,long,short)
2、String类型
3、Class类型
4、enum类型
5、Annotation类型
6、以上所有类型的数组
可以通过default来声明参数的默认值。
Annotation类型里面的参数怎么设定?常遵循如下规范:
第一:只能用public或默认(default)这两个访问权修饰。
例如,String value();这里把方法设为defaul默认类型;
第二:参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();这里的参数成员就为String;
第三:如果只有一个参数成员,最好把参数名称设为"value",后加小括号。
自定义注解的简单例子:
第一步:定义注解
package annotation.self;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 宠物名称注解
* @author chenzhengfeng
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface PetName {
String value() default "";
}
package annotation.self;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 宠物类型注解
* @author chenzhengfeng
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface PetType {
/**
* 类型枚举
*/
public enum Type{CAT,DOG,PIG,SNAKE};
/**
* 类型属性
*/
Type pet_type() default Type.DOG;
}
第二步:应用注解:
定义了注解,并在需要的时候给相关类,类属性加上注解信息即可,如下例。
packagepet;
importjava.lang.annotation.Annotation;
importannotation.self.PetName;
importannotation.self.PetType;
importannotation.self.PetType.Type;
@PetName("mimi")
@PetType(pet_type =Type.PIG)
public class Pet {
private String petName;
private String petType;
public String showAll() {
return this.petName + " " + this.petType;
}
public String getPetName() {
return petName;
}
public void setPetName(String petName) {
this.petName = petName;
}
public String getPetType() {
return petType;
}
public void setPetType(String petType) {
this.petType = petType;
}
public static void main(String[] args) {
Pet pet1 = new Pet();
System.out.println(pet1.showAll());
}
}
通过以上例子,可以看出如果没有响应的注解信息处理流程,注解可以说是没有实用价值。
如何让注解真真的发挥作用,主要就在于注解处理方法,下一步我们将学习注解信息的获取和处理。