Установка значения аннотированного поля с использованием отражения в классе generi c. (IllegalArgumentException) - PullRequest
2 голосов
/ 03 августа 2020

Я столкнулся с проблемой, которая подразумевает отражение, аннотации и обобщения в Java. У меня есть класс, который создает новый экземпляр типа generi c с именем B. Затем он будет искать любой Field с аннотацией MyCustomAnnotation и устанавливать его значение на определенное значение.

Класс, который это делает:

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. Должно быть, мне чего-то не хватает, но я не могу понять этого.

Любая помощь приветствуется!

1 Ответ

1 голос
/ 03 августа 2020

Вот ваша проблема…

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

Вот ваше исправление

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

Вот docs

publi c void set (Object obj, Object value)

...

Параметры:

obj - объект, поле которого необходимо изменить

value - новое значение для поля изменяемый объект

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...