-
注意
- 注解方法不能带有参数;
- 注解方法返回值类型限定为:基本类型、String、Enums、Annotation或者是这些类型的数组;
- 注解方法可以有默认值;
- 注解本身能够包含元注解,元注解被用来注解其它注解。
-
四类注解
这里有四种类型的元注解:
1. @Documented —— 指明拥有这个注解的元素可以被javadoc此类的工具文档化。这种类型应该用于注解那些影响客户使用带注释的元素声明的类型。如果一种声明使用Documented进行注解,这种类型的注解被作为被标注的程序成员的公共API。
- @Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中,在class字节码文件中不包含
- @Retention(RetentionPolicy.CLASS) // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
- @Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
2. @Target —— 指明该类型的注解可以注解的程序元素的范围。该元注解的取值可以为TYPE,METHOD,CONSTRUCTOR,FIELD等。如果Target元注解没有出现,那么定义的注解可以应用于程序的任何元素。
3. @Inherited —— 指明该注解类型被自动继承。如果用户在当前类中查询这个元注解类型并且当前类的声明中不包含这个元注解类型,那么也将自动查询当前类的父类是否存在Inherited元注解,这个动作将被重复执行知道这个标注类型被找到,或者是查询到顶层的父类。
4.@Retention —— 指明了该Annotation被保留的时间长短。RetentionPolicy取值为SOURCE,CLASS,RUNTIME。
小栗子
- DefineAnnotation.java
package pan;
import java.lang.annotation.*;
/**
* Created by panzhangbao on 2017/7/24.
*/
public class DefineAnnotation {
// 用于构造方法
@Target(ElementType.CONSTRUCTOR)
// 在运行时加载 Annotation 到 JVM 中
@Retention(RetentionPolicy.RUNTIME)
// 定义一个具有默认值 String 型成员
public @interface Constructor_Annotation{
String value() default "默认构造方法";
}
// 用于字段、方法和参数
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Field_Method_Parameter_Annotation{
String desctibe(); // 定义一个没有默认值的 String 型成员
Class type() default void.class; // 定义一个具有默认值的 Class 型成员
}
}
- Record.java
package pan;
/**
* Created by panzhangbao on 2017/7/24.
*/
public class Record {
// 注释字段
@DefineAnnotation.Field_Method_Parameter_Annotation(desctibe = "编号", type = int.class) int id;
@DefineAnnotation.Field_Method_Parameter_Annotation(desctibe = "姓名", type = String.class) String name;
// 采用默认值注释构造方法
@DefineAnnotation.Constructor_Annotation()
public Record(){}
@DefineAnnotation.Constructor_Annotation("立即初始化构造方法")
public Record(// 注释构造方法
@DefineAnnotation.Field_Method_Parameter_Annotation(desctibe = "编号", type = int.class)int id,
@DefineAnnotation.Field_Method_Parameter_Annotation(desctibe = "姓名", type = String.class)String name){
this.id = id;
this.name = name;
}
// 以下为 getter/setter 方法
@DefineAnnotation.Field_Method_Parameter_Annotation(desctibe = "获得编号", type = int.class)
public int getId(){ // 注释方法
return id;
}
@DefineAnnotation.Field_Method_Parameter_Annotation(desctibe = "设置编号")
// 采用默认值注释方法
public void setId(@DefineAnnotation.Field_Method_Parameter_Annotation(desctibe = "编号", type = int.class)int id){
this.id = id;
}
@DefineAnnotation.Field_Method_Parameter_Annotation(desctibe = "获得姓名", type = String.class)
public String getName(){
return name;
}
@DefineAnnotation.Field_Method_Parameter_Annotation(desctibe = "设置姓名")
public void setName(
@DefineAnnotation.Field_Method_Parameter_Annotation(desctibe = "姓名", type = String.class)String name){
this.name = name;
}
}
- Main.java
package pan;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) {
// write your code here
// getConstructors();
// getVars();
// getMethod();
/**
* Annotation(注解) 可用于类、构造方法、成员变量、方法、参数等的声明中。
* 该功能并不影响程序的运行,但是会对编译器警告等辅助工具产生影响。
*/
Class<Record> recordClass = (Class<Record>) new Record().getClass();
Constructor[] declaredConstructors = recordClass.getDeclaredConstructors(); // 获得所有构造方法
for(int i = 0; i < declaredConstructors.length; i ++){
Constructor constructor = declaredConstructors[i];
// 查看是否具有指定类型的注释
if (constructor.isAnnotationPresent(DefineAnnotation.Constructor_Annotation.class)){
// 获取指定类型的注释
DefineAnnotation.Constructor_Annotation ca =
(DefineAnnotation.Constructor_Annotation)constructor.getAnnotation(DefineAnnotation.Constructor_Annotation.class);
// 获得注释信息
System.out.println("打印注释信息:" + ca.value());
}
Annotation[][] paramsAnnotation = constructor.getParameterAnnotations();
for (int j = 0; j < paramsAnnotation.length; j ++){
// 获得指定参数注释的长度
int length = paramsAnnotation[j].length;
if (length == 0){
System.out.println("未添加 Annotation 的参数");
}else {
for (int k = 0; k < length; k++){
// 获得参数的注释
DefineAnnotation.Field_Method_Parameter_Annotation pa =
(DefineAnnotation.Field_Method_Parameter_Annotation)paramsAnnotation[j][k];
System.out.print("打印参数描述:" + pa.desctibe()); // 获得参数描述
System.out.println(" " + pa.type()); // 获得参数类型
}
}
}
}
// 编写访问字段的 Annotation 的信息代码
// 获得所有字段
Field[] declaedFields = recordClass.getDeclaredFields();
for (int i = 0; i < declaedFields.length; i ++){
Field field = declaedFields[i];
// 查看是否具有指定类型的注释
if (field.isAnnotationPresent(DefineAnnotation.Field_Method_Parameter_Annotation.class
)){
// 获得指定类型的注释
DefineAnnotation.Field_Method_Parameter_Annotation fa =
field.getAnnotation(DefineAnnotation.Field_Method_Parameter_Annotation.class);
System.out.print("打印字段描述:" + fa.desctibe());
System.out.println(" " + fa.type());
}
}
// 最后编写访问方法及其包含参数的 Annocation 信息的代码
Method[] methods = recordClass.getDeclaredMethods();
for (int i = 0; i < methods.length; i++){
Method method = methods[i];
// 查看是否具有指定类型的注释
if (method.isAnnotationPresent(DefineAnnotation.Field_Method_Parameter_Annotation.class)){
// 获得所有类型的注释
DefineAnnotation.Field_Method_Parameter_Annotation ma =
method.getDeclaredAnnotation(DefineAnnotation.Field_Method_Parameter_Annotation.class);
System.out.print("打印方法的描述:" + ma.desctibe());
System.out.println(" "+ ma.type());
}
Annotation[][] paramsAnnotations = method.getParameterAnnotations();
for (int j = 0; j < paramsAnnotations.length; j ++){
// 获得指定参数注释的长度
int length = paramsAnnotations[j].length;
if (length == 0){
System.out.println("未添加 Annotation 的参数2");
}else {
for (int k = 0; k < length; k++){
// 获得指定类型的注释
DefineAnnotation.Field_Method_Parameter_Annotation pa =
(DefineAnnotation.Field_Method_Parameter_Annotation)paramsAnnotations[j][k];
System.out.print("打印参数描述2:" + pa.desctibe()); // 获得参数描述
System.out.println(" " + pa.type()); // 获得参数类型
}
}
}
}
}
}
/** print:
打印注释信息:默认构造方法
打印注释信息:立即初始化构造方法
打印参数描述:编号 int
打印参数描述:姓名 class java.lang.String
打印字段描述:编号 int
打印字段描述:姓名 class java.lang.String
打印方法的描述:获得姓名 class java.lang.String
打印方法的描述:设置姓名 void
打印参数描述2:姓名 class java.lang.String
打印方法的描述:获得编号 int
打印方法的描述:设置编号 void
打印参数描述2:编号 int
*/
网友评论