在泛型 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);
...
...
field.set(instance, myValue);
...
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
…
我一直面临 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);
...
...
field.set(instance, myValue);
...
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
…