Создание универсального компоновщика JavaBean - PullRequest
0 голосов
/ 11 мая 2018

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

Цель состоит в том, чтобы использовать его следующим образом:

        MyValueObject myvalueObject = new GenericBuilder<MyValueObject>(MyValueObject.class)
            .with("someIntegerProperty", 12)
            .build();

Вот моя попытка до сих пор использовать отражение:

public class GenericBuilder<T> {
    private T bean;
    private Class<T> clazz;

    public GenericBuilder(Class<T> clazz) {
        this.clazz = clazz;

        Constructor<?> constructor = null;
        try {
            constructor = Class.forName(clazz.getCanonicalName()).getConstructor();
            bean = (T) constructor.newInstance();
        } catch (NoSuchMethodException | ClassNotFoundException | IllegalAccessException | InvocationTargetException | InstantiationException e) {
            e.printStackTrace();
        }
    }

    public <S> GenericBuilder<T> with(String propertyName, S value) {
        Method method;
        try {
            method = Class.forName(clazz.getCanonicalName())
                .getMethod("set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1), Object.class);
            method.invoke(bean, (S) value);
        } catch (NoSuchMethodException | ClassNotFoundException | InvocationTargetException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return this;
    }

    public T build() {
        return bean;
    }
}

Однако вызов метода завершается неудачно с NoSuchMethodException, поскольку определенный тип параметра во время выполнения - Object вместо правильного типа. Это происходит из-за стирания типа .

Я знаю, что могу получить фактический тип параметра с помощью method.getParameterTypes()[0], но я не могу использовать его для приведения value таким образом

method.invoke(bean, (method.getParameterTypes()[0]) value); //compiler error

Как я могу это исправить?

1 Ответ

0 голосов
/ 11 мая 2018

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

Вот новая реализация with(String propertyName, S value) метода:

public <S> GenericBuilder<T> with(String propertyName, S value) {
    try {
        String target = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
        for (Method m : clazz.getMethods()) {
            if (target.equals(m.getName())) {
                Class<?>[] params = m.getParameterTypes();
                if (params.length == 1) {
                    m.invoke(bean, value);
                    break;
                }
            }
        }
    } catch (InvocationTargetException | IllegalAccessException e) {
        e.printStackTrace();
    }
    return this;
}
...