这是根据一篇博客写的,原文链接为:https://blog.csdn.net/wangpengzhi19891223/article/details/78131137/#commentBox
我们来逐个讲述编写自定义Annotations的要点。
J2SE5.0版本在 java.lang.annotation提供了四种元注解,专门注解其他的注解:
@Documented –注解是否将包含在JavaDoc中
@Retention –什么时候使用该注解
@Target? –注解用于什么地方
@Inherited – 是否允许子类继承该注解
@Documented–一个简单的Annotations标记注解,表示是否将注解信息添加在java文档中。
@Retention– 定义该注解的生命周期。
RetentionPolicy.SOURCE – 在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。@Override, @SuppressWarnings都属于这类注解。
RetentionPolicy.CLASS – 在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式。
RetentionPolicy.RUNTIME– 始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。
@Target – 表示该注解用于什么地方。如果不明确指出,该注解可以放在任何地方。以下是一些可用的参数。需要说明的是:属性的注解是兼容的,如果你想给7个属性都添加注解,仅仅排除一个属性
,那么你需要在定义target包含所有的属性。
ElementType.TYPE:用于描述类、接口或enum声明
ElementType.FIELD:用于描述实例变量
ElementType.METHOD
ElementType.PARAMETER
ElementType.CONSTRUCTOR
ElementType.LOCAL_VARIABLE
ElementType.ANNOTATION_TYPE 另一个注释
ElementType.PACKAGE 用于记录java文件的package信息
@Inherited – 定义该注释和子类的关系
注解处理的基础知识
方法1: T getAnnotation(Class annotationClass): 返回改程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。
方法2:Annotation[] getAnnotations():返回该程序元素上存在的所有注解。
方法3:boolean is AnnotationPresent(Class annotationClass):判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false.
方法4:Annotation[] getDeclaredAnnotations():返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。
以下实现自定义注解:
第一:定义三个自定义的注解类
第二:创建一个实体
第三:创建一个中间类
第四:测试
第一步的代码:创建三个自定义注解类
@Retention(RetentionPolicy.RUNTIME)
public @interface CarNameTarger {
String name() default "";
}
@Retention(RetentionPolicy.RUNTIME)
public @interface CarTypeTarger {
public String carType();
public static class Type{
public static final String benchi = "benchi";
}
}
@Retention(RetentionPolicy.RUNTIME)
public @interface CarSalerTarger {
public String salername();
public int age() default 1;
}
第二步代码:创建一个实体类,里面只含有三个字段。
/**
* @author chenxihua
* @Date 2018年9月14日
*/
public class BenCar {
@CarNameTarger(name="奔驰车")
private String name;
@CarTypeTarger(carType = CarTypeTarger.Type.benchi)
private String type;
@CarSalerTarger(salername="小华",age=24)
private String carInfo;
}
第三步代码:创建一个中间类,方便测试
/**
* @author chenxihua
* @Date 2018年9月14日
*/
public class CarInfoUtil {
public static void getFruitInfo(Class> clazz){
Field[] fields = clazz.getDeclaredFields();
for(Field field :fields){
if(field.isAnnotationPresent(CarNameTarger.class)){
CarNameTarger name = (CarNameTarger) field.getAnnotation(CarNameTarger.class);
// 下面被注释的输出语句是判断上面语句获取值的情况,可知道,上式是获取字段上注解的值,而不是获取注解类的值,
// System.out.println("汽车的中文名字是:"+name.toString());
// 输出的结果是: 汽车的中文名字是:@annontation.CarNameTarger(name=奔驰车)
// 由此可知,getAnnotation();方法的用处 (重点)
String carColour ="汽车的中文名:"+name.name();
System.out.println(carColour);
}
else if(field.isAnnotationPresent(CarTypeTarger.class)){
CarTypeTarger type= (CarTypeTarger) field.getAnnotation(CarTypeTarger.class);
String carType="汽车的类型:"+type.carType().toString();
System.out.println(carType);
}
else if(field.isAnnotationPresent(CarSalerTarger.class)){
CarSalerTarger saler= (CarSalerTarger) field.getAnnotation(CarSalerTarger.class);
String salerInfo=" 销售员姓名:"+saler.salername()+" 销售员年龄:"+ saler.age();
System.out.println(salerInfo);
}
}
}
}
第四步代码:测试:
@Test
public void testAnnoation(){
CarInfoUtil.getFruitInfo(BenCar.class);
}
测试结果:
汽车的中文名:奔驰车
汽车的类型:benchi
销售员姓名:小华 销售员年龄:24
总结:参考链接:https://www.cnblogs.com/JackZed/p/6888668.html
1:关于获取类的字段有两种方式:getFields()和getDeclaredFields()。我们先来看看这两者的区别吧
getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段。
getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段
同样类似的还有getConstructors()和getDeclaredConstructors()、getMethods()和getDeclaredMethods(),这两者分别表示获取某个类的构造函数,方法。
获取字段的名称
String fieldName = field.getName();
获取字段的修饰符
int fieldValue = field.getModifiers();//如:private、static、final等
与某个具体的修饰符进行比较
Modifier.isStatic(fieldValue)//看此修饰符是否为静态(static)
获取字段的声明类型
field.getType();//返回的是一个class
与某个类型进行比较
field.getType() == Timestamp.class
获取指定对象中此字段的值
Object fieldObject= field.get(user);//user可以看做是从数据库中查找出来的对象