慕尼黑8549860
要递归修改用给定注释注释的对象中的所有字段,我们必须首先确定所有字段。Class.getFields()将只返回“可访问的公共字段”。这不符合要求。因此我们必须使用Class.getDeclaredFields(). 这反过来只返回“由类声明”的字段。为了获得所有字段,我们必须向上遍历目标对象的类型层次结构,并为每个类型处理其声明的字段。对于每个字段,我们必须区分一些情况:阿Field 被标注为指定的注释。然后必须将给定的值应用于该字段。为了设置该值,该字段必须是(使)可访问且非最终的。AField 未使用指定的注释进行注释。那么要区分三种情况:该字段具有原始类型。那么它就不是一个可以包含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()实现了:@Overridepublic String toString() { return "s: " + s + " / b: [" + Optional.ofNullable(b).map(B::toString).orElse("null") + "]";}和类B已经toString()实现了这样的:@Overridepublic String toString() { return "a: " + a + " / b: " + b;}