簡體   English   中英

在通用 class 中使用反射設置帶注釋的字段值。(IllegalArgumentException)

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

我一直面臨一個問題,它暗示 Java 中的反射、注釋和 Generics。我有一個 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類型的 Field :

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();
        }
    }
}

程序的output為:

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);
...

這是您的解決方法……

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

這是文檔……

public void set(Object obj, Object 值) ...

...

參數:

obj - 應修改其字段的 object

value - 正在修改的 obj 字段的新值

……

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM