java.lang.IllegalArgumentException возникает при попытке установить экземпляр путем отражения

Моя цель — создать экземпляр для класса при вызове его метода получения, после чего установить значение для новых полей экземпляра. (в этом случае, показанный в коде, класс представляет собой строку, но это может быть другой класс «класс Like Person»)

...Аннотация объекта:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface Entity {

    String visibileName();

}

...орудияIEventDesignDialog

      public class EventDesignDialog implements IEventDesignDialog{

        private String show;
        private String dateAndTimeDisplayFormat;
        private String eventType;


        @Entity(visibileName = "Show")
        public String getShow() {
            return this.show;
        }

        @Entity(visibileName = "Date And Time display format")
        public String getDateAndTimeDisplayFormat() {
            return this.dateAndTimeDisplayFormat;
        }

        @Entity(visibileName = "Event Type")
        public String getEventType() {
            System.out.println("get event type method invokde successfully");
            return this.eventType;
        }
}

IEventDesignDialog интерфейс:

public interface IEventDesignDialog extends IPage{

    public String getShow();

    public String getDateAndTimeDisplayFormat();

    public String getEventType();


}

IPage интерфейс:

public interface IPage {

}

Реализация динамического прокси:

public class IPageProxy implements InvocationHandler {
    private List<Method> entityMethods;



    private Class <? extends IPage> screenClazz;

    public IPageProxy(final Class <? extends IPage> screenClazz) {
        entityMethods = new ArrayList<>();
        getEntityAnnotatedMethods(screenClazz);
        // Accept the real implementation to be proxied
        this.screenClazz = screenClazz;
    }


    /**
     * create an page instance
     * @param type
     * @param
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static IPage getInstance(final Class<? extends IPage> type)
            throws InstantiationException, IllegalAccessException {

        List<Class<?>> interfaces = new ArrayList<>();
        interfaces.addAll(Arrays.asList(type.getInterfaces()));

        return (IPage) Proxy.newProxyInstance(
                type.getClassLoader(),
                findInterfaces(type),
                new IPageProxy(type)
             );

        /*return (IPage) Proxy.newProxyInstance(type.getClassLoader(),
               interfaces.toArray(new Class<?>[interfaces.size()])
                , new IPageProxy(type));*/
    }


    /**
     * get all methods that annotated with @Entity annotation
     * and add it for entityMethods array List
     * @param screenClazz
     */
    private void getEntityAnnotatedMethods(final Class <? extends IPage>  screenClazz) {
        // Scan each interface method for the specific annotation
        // and save each compatible method
        for (final Method m : screenClazz.getDeclaredMethods()) {
            if (m.isAnnotationPresent(Entity.class)) {
                entityMethods.add(m);
            }
        }
    }


    static Class<?>[] findInterfaces(final Class<? extends IPage> type) {
        Class<?> current = type;

        do {
            final Class<?>[] interfaces = current.getInterfaces();

            if (interfaces.length != 0) {
                return interfaces;
            }
        } while ((current = current.getSuperclass()) != Object.class);

        throw new UnsupportedOperationException("The type does not implement any interface");
    }



  @Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws InvocationTargetException,
        IllegalAccessException, IllegalArgumentException, InstantiationException, ParserConfigurationException, XPathExpressionException, NoSuchFieldException, SecurityException {

    Method methodToInvoke = null;

    for (Method methodFromClass : screenClazz.getMethods()) {
        if (methodFromClass.getName().equals(method.getName())) {
            methodToInvoke = methodFromClass;
            break;
        }
    }



    String fieldName = method.getName().replaceAll("get", "");
    fieldName = Character.toLowerCase(fieldName.charAt(0)) + fieldName.substring(1, fieldName.length());

    Field getterMethodField = methodToInvoke.getDeclaringClass().getDeclaredField(fieldName);
    getterMethodField.setAccessible(true);

    Class<?> returnedType = method.getReturnType();

    try {
        *getterMethodField.set(getterMethodField.getType().newInstance(), "");*
    }catch (Exception e) {
        e.printStackTrace();
    }


    return methodToInvoke.invoke(screenClazz.newInstance(), args);
}

Основной класс:

public class Main {

    public static void main(String[] args) {
        try {

            ((EventDesignDialog)getInstance(EventDesignDialog.class)).getEventType();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }


    @SuppressWarnings("unchecked")
    public static <T extends IPage> T getInstance(final Class<? extends IPage> type) throws InstantiationException, IllegalAccessException {
        return (T) IPageProxy.getInstance(type);
    }

}

Следующее исключение возникает, когда эта строка кода вызывает метод: getterMethodField.set(getterMethodField.getType().newInstance(), "");

 java.lang.IllegalArgumentException: Can not set java.lang.String field abc.EventDesignDialog.eventType to java.lang.String
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:75)
at java.lang.reflect.Field.set(Field.java:764)
at abc.IPageProxy.invoke(IPageProxy.java:173)
at com.sun.proxy.$Proxy2.getEventType(Unknown Source)
at abc.Main.main(Main.java:9)

person Ali Taha    schedule 04.04.2019    source источник
comment
Дайте мне знать, если я недостаточно ясно выразился. Иногда я слишком вдаюсь в детали.   -  person LppEdd    schedule 04.04.2019


Ответы (1)


methodToInvoke.getDeclaringClass()

возвращает Class<? extends IPage>.
Пока

getterMethodField.getType()

возвращает String.

Таким образом, вы пытаетесь установить значение поля eventType внутри класса java.lang.String.
Не совсем правильно ;)

 getterMethodField.set(getterMethodField.getType().newInstance(), "")
 ^---------------^     ^---------------------------------------^
      field of              new instance of java.lang.String
Class<? extends IPage>  Here you need an instance of ? extends IPage

Что вам нужно, это

getterMethodField.getDeclaringClass().newInstance()

В любом случае, я не знаю, какой в ​​этом смысл, так как вновь созданный экземпляр тут же "теряется".
Может быть, вы хотели это сделать?

    try {
        final Object instance = getterMethodField.getDeclaringClass().newInstance();
        getterMethodField.set(instance, "");
    } catch (final Exception e) {
        e.printStackTrace();
    }

    return methodToInvoke.invoke(instance, args);
}
person LppEdd    schedule 04.04.2019