как в целом сравнить целые java beans?

Я пытался найти библиотеку org.apache.commons.beanutils для метода / идиомы для оценки равенства всех свойств между двумя экземплярами, то есть универсальным методом equals () для beans.
Есть ли простой способ сделать это, используя эту библиотеку? Или я ошибаюсь? Спасибо.


person ysouter    schedule 23.01.2009    source источник
comment
В этом контексте может быть интересна библиотека xtendbeans; см. полный пример этого другого вопроса SO.   -  person vorburger    schedule 30.08.2016


Ответы (4)


Попробуйте EqualsBuilder.reflectionEquals () из commons-lang. EqualsBuilder имеет набор методов для включения всех полей, всех непереходных полей и всех полей, кроме определенных.

Если ничего не помогает, код может служить хорошим примером того, как это реализовать.

person Aaron Digulla    schedule 23.01.2009
comment
Имейте в виду, что это не рекурсивно - поэтому, если у вас есть вложенные bean-компоненты (т.е. свойство bean-компонента является другим bean-компонентом), они должны реализовать себя равных. reflectionEquals просто вызывает equals для каждого свойства, это больше не отражается на классе. - person artbristol; 08.10.2012
comment
@artbristol: +1, но будьте осторожны, рекурсивное равенство: вы можете легко попасть в петлю, когда бобы образуют циклы. - person Aaron Digulla; 08.10.2012
comment
Также полезен ReflectionDiffBuilder для поиска различий. - person Alexey Sviridov; 06.06.2019

Чтобы напрямую ответить на ваш вопрос, вы можете использовать отражение для проверки равенства bean-компонентов. Есть несколько препятствий, о которых вам нужно знать.

Существуют правила поведения equals () и hashcode (). Эти правила говорят о симметрии, согласованности и рефлексивности, что может быть трудно сделать, когда ваш метод equals ведет себя динамически в зависимости от другого объекта, который вы передаете.

Интересное чтение: http://www.geocities.com/technofundo/tech/java/equalhash.html

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

Сказав все это, вот несколько (в старом стиле) методов получения геттеров, сеттеров и свойств, которые я написал давно:

private Map getPrivateFields(Class clazz, Map getters, Map setters) {
    Field[] fields = clazz.getDeclaredFields();
    Map m = new HashMap();
    for (int i = 0; i < fields.length; i++) {
        int modifiers = fields[i].getModifiers();
        if (Modifier.isPrivate(modifiers) && !Modifier.isStatic(modifiers) && !Modifier.isFinal(modifiers)) {
            String propName = fields[i].getName();
            if (getters.get(propName) != null && setters.get(propName) != null) {
                m.put(fields[i].getName(), fields[i]);
            }
        }
    }
    return m;
}

Получатели:

private Map getGetters(Class clazz) {
    Method[] methods = clazz.getMethods();
    Map m = new HashMap();
    for (int i = 0; i < methods.length; i++) {
        if (methods[i].getName().startsWith("get")) {
            int modifiers = methods[i].getModifiers();
            if (validAccessMethod(modifiers)) {
                m.put(getPropertyName(methods[i].getName()), methods[i]);
            }
        }
    }
    return m;
}

И сеттеры:

private Map getSetters(Class clazz, Map getters) {
    Method[] methods = clazz.getMethods();
    Map m = new HashMap();
    for (int i = 0; i < methods.length; i++) {
        if (methods[i].getName().startsWith("set")) {
            int modifiers = methods[i].getModifiers();
            String propName = getPropertyName(methods[i].getName());
            Method getter = (Method) getters.get(propName);

            if (validAccessMethod(modifiers) && getter != null) {
                Class returnType = getter.getReturnType();
                Class setType = methods[i].getParameterTypes()[0];
                int numTypes = methods[i].getParameterTypes().length;

                if (returnType.equals(setType) && numTypes == 1) {
                    m.put(propName, methods[i]);
                }
            }
        }
    }
    return m;
}

Может быть, ты сможешь использовать это, чтобы свернуть свою собственную.

Изменить: Конечно, билдер отражения в Ответ Аарона Дигуллы намного лучше, чем мои ручные работы.

person Rolf    schedule 23.01.2009
comment
логические геттеры называются isFoo (), поэтому код потребует небольшого улучшения в getGetters () - person Vladimir Dyuzhev; 15.06.2012

Как упоминалось выше, реализация на основе отражения будет делать то, что вы хотите. Я просто хотел предупредить вас, что рефлексия стоит довольно дорого, и такая реализация может быть сравнительно медленной. Если вам просто нужно время от времени проводить сравнения, все будет в порядке. Однако, если у вас есть огромные наборы данных и частые проверки равенства (например, фильтрация больших таблиц), у вас могут возникнуть проблемы.

person Rahel Lüthy    schedule 23.01.2009
comment
Действительно хороший аргумент. У jguru есть хорошее сравнение в Интернете: jguru.com/faq/view.jsp?EID = 246569 - person Rolf; 23.01.2009

Или, хотя это и не прямой ответ на ваш вопрос, но он может быть ответом на вашу проблему (т. Е. Устраните необходимость выполнять шаблонный код при сверхбыстром)

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

Источник> Создать хэш-код и равно ...

а затем выберите поля, это супер эффективно! : D

Ура, и я надеюсь, что это поможет любому, кто приходит сюда с целью сократить время на написание шаблона.

PS: Я уверен, что другие популярные IDE должны иметь аналогичные функции.

person João Antunes    schedule 30.01.2016
comment
Я действительно хотел бы знать, почему за эту опцию проголосовали -1. Это очень быстрый способ создания таких методов. И большинство IDE поддерживают его - это не так дорого, как рефлексия - и этот ответ в целом полезен - вот почему я поместил его здесь ... и поэтому я не буду брать его отсюда - я бы хотел, чтобы это было обязательным, чтобы объяснить, почему один отрицает вещи - person João Antunes; 28.03.2019
comment
FWIW Я думаю, что этот ответ не менее актуален, чем ответ, предупреждающий, что размышления могут быть медленными. - person Bampfer; 27.06.2019