Как использовать отражение, чтобы вызвать метод с примитивными аргументами? - PullRequest
0 голосов
/ 24 декабря 2018

Я пытаюсь создать метод invokeMethod(String methodName, Object...args), который вызывает метод из суперкласса текущего экземпляра.Я попробовал следующую реализацию.

    public void invokeMethod(String methodName, Object...args) {
        //Array to hold the classes of the arguments
        Class<?>[] classes = new Class<?>[args.length]; 
        //Initialize each class in the array to the class of each argument 
        for(int i = 0; i < args.length; i++)
            classes[i] = args[i].getClass();
        try {
            //find the method
            Method m = this.getClass().getMethod(methodName, classes);
            //invoke the method
            m.invoke(this, args);
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }

Проблема с этой реализацией состоит в том, что, если я пытаюсь вызвать метод с примитивными параметрами, я получаю NoSuchMethodException, потому что он ищет метод с параметрами, тип которых является эквивалентом класса оболочки.

Например, если я пытаюсь вызвать метод с подписью line(float, float, float, float), пытаясь invokeMethod("line", 50f, 50f, 50f, 50f), я получаю исключение, похожее на

java.lang.NoSuchMethodException: DynamicSketch.line(java.lang.Float, java.lang.Float, java.lang.Float, java.lang.Float)
at java.base/java.lang.Class.getMethod(Class.java:2109)
at DynamicSketch.invokeMethod(DynamicSketch.java:32)
at DynamicSketch.setup(DynamicSketch.java:19)
at processing.core.PApplet.handleDraw(PApplet.java:2412)
at processing.awt.PSurfaceAWT$12.callDraw(PSurfaceAWT.java:1557)
at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:316)

Есть ли способ сделать мой invokeMethod метод работает с примитивными аргументами?

Редактировать: Решение здесь не работает, потому что я не знаю точно, какие примитивные типы присутствуют в сигнатуре при выполнении моего метода.Я хочу иметь возможность выполнять методы, такие как size(int, int) и line(float, float ,float ,float), используя мой метод, и решение в ссылке не легко с этим работать.Единственное решение, которое я вижу, это определить оператор if для каждого возможного метода в суперклассе, а затем использовать решение в ссылке, но я хотел менее утомительный способ.

1 Ответ

0 голосов
/ 24 декабря 2018

Когда такие аргументы, как 10 или 10.0f передаются в метод, они автоматически переносятся, поскольку тип параметра равен Object....

Поэтому вам необходимо проверить наличие этих типов оболочеки разверните их.Ваш цикл for может выглядеть следующим образом:

for(int i = 0; i < args.length; i++) {
    if (args[i].getClass() == Integer.class) {
        classes[i] = int.class;
    } else if (args[i].getClass() == Float.class) {
        classes[i] = float.class;
    } else if (args[i].getClass() == Double.class) {
        classes[i] = double.class;
    } else {
        classes[i] = args[i].getClass();
    }
}

Я только добавил 3 случая здесь, вы можете добавить остальные 5 самостоятельно.

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

  1. развернуть все типы оболочек
  2. попытаться найти метод с этими типами без оболочек
  3. Еслине найдено, оберните их снова
  4. найдите метод, используя типы оберток.

Редактируйте:

Как предложил Хольгер в комментариях, вы также можете разрешитьJVM найдет подходящий для вас метод, используя

new Statement(this, methodName, args).execute();

Docs для класса Statement.

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