Как преобразовать строку в функцию установки, если метод принимает примитивный тип?

Пока я не предлагаю решение вложенных форм (это не работает надежно), я предоставляю обходной путь, который работает для меня:

Сценарий использования: суперформа, позволяющая изменять N элементов однажды. Он имеет кнопку «Отправить все» внизу. Каждый элемент хочет иметь свою собственную вложенную форму с кнопкой «Отправить элемент № N». Но не может ...

В этом случае можно фактически использовать одну форму, а затем иметь имя кнопок submit_1 .. submit_N и submitAll и обрабатывать их на стороне сервера, только глядя на параметры, оканчивающиеся на _1, если имя кнопки было submit_1.

<form>
    <div id="item1">
        <input type="text" name="foo_1" value="23">
        <input type="submit" name="submit_1" value="Submit Item #1">
    </div>
    <div id="item2">
        <input type="text" name="foo_2" value="33">
        <input type="submit" name="submit_2" value="Submit Item #2">
    </div>
    <input type="submit" name="submitAll" value="Submit All Items">
</form>

Хорошо, поэтому не так много, но это делает работу.

-1
задан Boann 25 June 2019 в 19:22
поделиться

4 ответа

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

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

Method method = PropertyUtils.getReadMethod( new PropertyDescriptor(key, resultClass));
1
ответ дан k5_ 25 June 2019 в 19:22
поделиться

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

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

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

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

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

0
ответ дан GhostCat 25 June 2019 в 19:22
поделиться

Вы не объяснили цель этого, но если я вас правильно понимаю, 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;
        }
    }
    
0
ответ дан Boann 25 June 2019 в 19:22
поделиться

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

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

    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
ответ дан erickson 25 June 2019 в 19:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: