在泛型 class 中使用反射设置带注释的字段值。 (非法参数异常)

Setting annotated field value using reflection in generic class. (IllegalArgumentException)

我一直面临 Java 中涉及反射、注解和泛型的问题。我有一个 class,它创建了一个名为 B 的泛型类型的新实例。然后它将搜索任何带有 MyCustomAnnotation 注释的 Field 并将其值设置为确定的值。

这样做的class是:

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class MyInstanceCreator<B> {
    
    private final String myValue = "Hello world!";
    
    public B createInstance(Class<B> classType) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        B obj = classType.getConstructor().newInstance();
        for(Field f: classType.getDeclaredFields()) {
            if(f.isAnnotationPresent(MyCustomAnnotation.class)) {
                System.out.println("Is annotated!");
                updateField(obj, f);
            }
        }
        return obj;
    }
    
    private void updateField(B instance, Field field) throws IllegalAccessException {
        field.setAccessible(true);
        field.set(myValue, instance);
        field.setAccessible(false);
    }
    
}

注解class:

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomAnnotation {}

自定义类型有一个类型为 String:

的注释字段
public class MyCustomType {
    
    @MyCustomAnnotation
    private String value;
    
    public String getValue() {
        return value;
    }
    
}

最后我的主要 class 是:

public class MyClass {
    public static void main(String args[]) {
        try {
            MyInstanceCreator<MyCustomType> iCreator = new MyInstanceCreator<>();
            MyCustomType myObj = iCreator.createInstance(MyCustomType.class);
            System.out.println(myObj.getValue());
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

程序的输出是:

Is annotated!

java.lang.IllegalArgumentException: Can not set java.lang.String field MyCustomType.value to java.lang.String
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
    at java.base/jdk.internal.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:75)
    at java.base/java.lang.reflect.Field.set(Field.java:780)
    at MyInstanceCreator.updateField(MyInstanceCreator.java:21)
    at MyInstanceCreator.createInstance(MyInstanceCreator.java:13)
    at MyClass.main(MyClass.java:5)

我不明白为什么反射不能像 IllegalArgumentException 消息所说的那样将 java.lang.String 值分配给 java.lang.String 字段。我一定是遗漏了什么,但我似乎无法弄明白。

感谢任何帮助!

这是你的问题…

...
field.set(myValue, instance);
...

Here's your fix

...
field.set(instance, myValue);
...

Here are the docs

public void set​(Object obj, Object value)

...

Parameters:

obj - the object whose field should be modified

value - the new value for the field of obj being modified