英文:
Setting annotated field value using reflection in generic class. (IllegalArgumentException)
问题
我一直遇到一个问题,涉及Java中的反射、注解和泛型。我有一个类,它创建了一个泛型类型B
的新实例。然后它会搜索具有MyCustomAnnotation
注解的任何Field
,并将其值设置为一个确定的值。
执行这个操作的类是:
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);
}
}
注解类:
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;
}
}
最后,我的主类是:
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)
对我来说,不太明白为什么反射无法将java.lang.String
值分配给java.lang.String
字段,正如IllegalArgumentException
消息所说。我一定漏掉了什么,但我似乎找不到答案。
感谢任何帮助!
英文:
I have been facing an issue that implies Reflection, Annotations and Generics in Java. I have a class that creates a new instance of a generic type called B
. Then it will search for any Field
with the MyCustomAnnotation
annotation and sets its value to a determined one.
The class that does this is:
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);
}
}
The annotation class:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomAnnotation {}
The custom type has an annotated Field of type String
:
public class MyCustomType {
@MyCustomAnnotation
private String value;
public String getValue() {
return value;
}
}
Finally my main class is:
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();
}
}
}
The output of the program is:
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)
It does not make any sense to me why reflection cannot assign a java.lang.String
value to a java.lang.String
field as the IllegalArgumentException
message says. I must be missing something but I can't seem to figure it out.
Any help is appreciated!
答案1
得分: 1
以下是您的问题:
...
field.set(myValue, instance);
...
以下是您的修复:
这里是您的修复...
...
field.set(instance, myValue);
...
这里是文档:
这里是文档...
public void set(Object obj, Object value)...
...
Parameters:
obj - 应修改其字段的对象
value - 要修改的 obj 字段的新值...
> …
英文:
Here's your problem…
...
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
>
> …
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论