先看代码例子:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//标记再属性上的注解,想要实现属性的默认值
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyTestAnnotation {
String value();
}
自定义注解时,需要添加两个重要的注解:
@Retention
用于标识注解能够保留多长时间,默认值为 RetentionPolicy.CLASS.
关于RetentionPolicy枚举类:
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
* 保留在源文件种
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
* 保留在class文件中,加载到JVM时丢失
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
* 保留在程序运行期间.
*/
RUNTIME
}
RetentionPolicy.RUNTIME 在运行期间也会有效.一般....就用它.
也许另外两个时辅助作用.
@Target
用域标识注解可以使用在什么地方.枚举类中讲的很清楚了,这里再贴一下.
关于ElementType枚举类:
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE,
/**
* Module declaration.
*
* @since 9
*/
MODULE
}
自定义一个实体类
public class TestModel {
@MyTestAnnotation("我的注解")
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return "TestModel{" +
"value=‘" + value + ‘\‘‘ +
‘}‘;
}
}
运行测试方法查看输出结果
public class TestAnnotation {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
TestModel testModel1 = new TestModel();
testModel1.setValue("我自己放的value");
TestModel testModel2 = new TestModel();
//setAnnotationValue(testModel2);//下面的步骤需要用到的方法
System.out.println(testModel1);
System.out.println(">>>>>>>>>>>>>>>>>>");
System.out.println(testModel2);
}
}
结果:
TestModel{value=‘我自己放的value‘}
>>>>>>>>>>>>>>>>>>
TestModel{value=‘null‘}
它并没有生效.
? 丢失的步骤
仅仅是写上注解,代码中并没有自动地去识别这个注解,然后去做想要地事情.
我们需要通过代码来检测注解,然后实现自己的逻辑.
这里通过反射来进行默认值的设置.
private static void setAnnotationValue(Object o) throws NoSuchFieldException, IllegalAccessException {
Field field = o.getClass().getDeclaredField("value");
field.setAccessible(true);
if(field.isAnnotationPresent(MyTestAnnotation.class)){
String settingValue = (String) field.get(o);//这里通过反射拿到value属性的值
if(!StringUtils.isEmpty(settingValue)){//如果value属性不为空,就返回
return;
}
MyTestAnnotation myTestAnnotation = field.getAnnotation(MyTestAnnotation.class);
String value = myTestAnnotation.value();//拿到注解中设置的值
field.set(o,value);//将注解中的值赋值给当前对象
}
}
再次查看输出结果:
TestModel{value=‘我自己放的value‘}
>>>>>>>>>>>>>>>>>>
TestModel{value=‘我的注解‘}
原文:https://www.cnblogs.com/reclusiveone/p/14814870.html