3 回答
TA贡献1818条经验 获得超11个赞
要递归修改用给定注释注释的对象中的所有字段,我们必须首先确定所有字段。
Class.getFields()
将只返回“可访问的公共字段”。这不符合要求。因此我们必须使用Class.getDeclaredFields()
. 这反过来只返回“由类声明”的字段。为了获得所有字段,我们必须向上遍历目标对象的类型层次结构,并为每个类型处理其声明的字段。
对于每个字段,我们必须区分一些情况:
阿
Field
被标注为指定的注释。然后必须将给定的值应用于该字段。为了设置该值,该字段必须是(使)可访问且非最终的。A
Field
未使用指定的注释进行注释。那么要区分三种情况:该字段具有原始类型。那么它就不是一个可以包含
String
字段的对象。该字段具有数组类型。那么它不能包含一个
String
字段。否则:该字段具有引用类型。然后必须(使其)可访问,以检查它是否设置了值,并在这种情况下再次递归处理其字段 1) 和 2)。
要检查是否在字段上设置了注释,我们使用Field.getAnnotation(myAnnotationClass)
wheremyAnnotationClass
声明为Class<MyAnnotation>
。但是我们必须注意一些额外的事情:只有在以下情况下Field.getAnnotation(myAnnotationClass)
才会返回字段的注释
它已设置(非常不言自明)
MyAnnotation
本身用@Retention(RetentionPolicy.RUNTIME)
.
相应的代码如下所示:
public static <T extends Annotation> void setValueOnAnnotatedFields(String s, Class<T> annotationClass, Object target) {
if (target != null) {
// traversing the type hierarchy upward to process fields declared in classes target's class extends
Class<?> clazz = target.getClass();
do {
setValueOnAnnotatedDeclaredFields(s, annotationClass, target, clazz);
}
while ((clazz = clazz.getSuperclass()) != null);
}
}
private static <T extends Annotation> void setValueOnAnnotatedDeclaredFields(String s, Class<T> annotationClass, Object target, Class<?> clazz) {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.getAnnotation(annotationClass) != null) {
set(field, target, s);
} else if (!field.getType().isPrimitive() && !field.getType().isArray()) {
setValueOnAnnotatedFields(s, annotationClass, get(field, target));
}
}
}
protected static void set(Field field, Object target, String value) {
try {
makeFiieldAccessibleNotFinal(field, target);
field.set(target, value);
}
catch (Exception e) {
String message = String.format("Failed to set the value on field %s", target.getClass().getSimpleName() + "." + field.getName());
throw new IllegalStateException(message, e);
}
}
protected static Object get(Field field, Object target) {
try {
makeFiieldAccessibleNotFinal(field, target);
return field.get(target);
}
catch (Exception e) {
String message = String.format("Failed to get the value on field %s", target.getClass().getSimpleName() + "." + field.getName());
throw new IllegalStateException(message, e);
}
}
protected static void makeFiieldAccessibleNotFinal(Field field, Object target) {
try {
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
}
catch (Exception e) {
String message = String.format("Failed to remove final declaration of field %s", field.getName());
throw new IllegalStateException(message, e);
}
try {
field.setAccessible(true);
}
catch (Exception e) {
String message = String.format("Failed to make field %s accessible", field.getName());
throw new IllegalStateException(message, e);
}
}
一个例子:
public static void main(String[] args) {
A a = new A();
System.out.println(a); // s: null / b: [null]
setValueOnAnnotatedFields("1", MyAnnotation.class, a);
System.out.println(a); // s: 1 / b: [null]
a.b = new B();
setValueOnAnnotatedFields("2", MyAnnotation.class, a);
System.out.println(a); // s: 2 / b: [a: 2 / b: null]
}
这意味着类A已经toString()实现了:
@Override
public String toString() {
return "s: " + s + " / b: [" + Optional.ofNullable(b).map(B::toString).orElse("null") + "]";
}
和类B已经toString()实现了这样的:
@Override
public String toString() {
return "a: " + a + " / b: " + b;
}
添加回答
举报