Как преобразовать строку в функцию установки, если метод принимает примитивный тип? - PullRequest
0 голосов
/ 25 июня 2019

Я пытаюсь сгенерировать установщик для класса, который принимает параметр типа примитива, но я получаю исключение, так как разрешены только не примитивы.

Для этого я беру строку и преобразовываюэто именно то, как функция находится в моем POJO, но, описывая тип параметра (int), он принимает свой класс-обертку (Integer).

Method method = resultClass.getClass().getMethod(getSetMethod(key), value.getClass());


private String getSetMethod(String key) {
    key = key.substring(0, 1).toUpperCase() + key.substring(1);
    key = "set"+key;
    return key;
}

Может кто-нибудь сказать мне, если есть альтернативный способсоздать этот метод, который работает как для примитивных, так и для не примитивных типов?

Ответы [ 4 ]

1 голос
/ 25 июня 2019

Если у вас есть возможность добавить библиотеки.Библиотека commons-beanutils может использоваться для обработки bean-компонентов и свойств.

В вашем случае вы можете сделать:

Method method = PropertyUtils.getReadMethod( new PropertyDescriptor(key, resultClass));
0 голосов
/ 25 июня 2019

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

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

    Map<Class<?>, Class<?>> boxedToPrimitive = new HashMap<>();
    boxedToPrimitive.put(Integer.class, Integer.TYPE);
    boxedToPrimitive.put(Long.class, Long.TYPE);
    boxedToPrimitive.put(Boolean.class, Boolean.TYPE);
    ...

    String name = getSetMethod(key);
    Method method;
    try {
        method = target.getClass().getMethod(name, val.getClass());
    } catch (NoSuchMethodException missing) {
        Class<?> alt = boxedToPrimitive.get(val.getClass());
        if (alt == null) throw missing;
        method = target.getClass().getMethod(name, alt);
    }
    method.invoke(target, value);
0 голосов
/ 25 июня 2019

Может кто-нибудь сказать мне, есть ли альтернативный способ генерации этого метода, который работает как для примитивных, так и для не примитивных типов?

Ты не можешь этого сделать. У вас не может быть одного объекта метода, который работает для foo(int) и foo(Integer). Потому что это будут два разных метода.

Причина, по которой компилятор позволяет вам вызывать некоторые foo(Integer) с foo(5), заключается в том, что компилятор использует бокс, чтобы превратить 5 в объект Integer, а затем передать его.

Помните: компилятор решает во время компиляции, какой метод будет вызван. Когда есть два метода с одинаковыми именами с разными типами аргументов, то это с перегрузкой ... и происходит во время компиляции.

Короче говоря: либо вам нужно создать два объекта метода, либо вам необходимо предоставить необходимый код для вставки / распаковки между примитивными и коробочными ссылочными типами по мере необходимости!

0 голосов
/ 25 июня 2019

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

Но value.getClass() действительно не подходит для этого, потому что:

  1. Невозможно вернуть примитивный тип.
  2. Может возвращать подкласс типа параметра метода setter.
  3. Он бросит NPE, если value равно нулю.

Итак, несколько возможных альтернатив:

  1. Предоставьте сеттер в качестве лямбда-функции вместо попыток взломать вещи с помощью отражения. Это более производительно и более гибко, чем использование отражения.

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

  3. Или, сойти с ума, и взять первый метод, который вы видите, который имеет имя установщика, независимо от его типа:

    Method method;
    String name = getSetMethod(key);
    for (Method m : resultClass.getClass().getMethods()) {
        if (m.getName().equals(name)) {
            method = m;
            break;
        }
    }
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...