Я искал вокруг SOF, но не нашел такой основной вопрос, связанный с использованием BeanUtil.
У меня класс POJO, скажем, например UserPojo
чей код класса:
public class UserPojo{
private String name;
private int gender;
private int size;
//Setters
public void setName(String name) {this.name =name;}
public void setGender(int gender){this.gender=gender;}
public void setSize(int size) {this.size =size;}
//getters
public String getName() {return this.name;}
public int getGender(){return this.gender;}
public int getSize() {return this.size;}
}
Мой вопрос: как использовать BeanUtil для автоматического сравнения двух экземпляров этого компонента?
Я попробовал это:
final BeanComparator<UserPojo> comparator = new BeanComparator<UserPojo>();
final int comparison = comparator.compare(expectedPojo, receivedPojo);
Но это заканчивается следующей ошибкой:
java.lang.ClassCastException : UserPojo cannot be cast to java.lang.Comparable
Я понимаю, что мой Pojo должен реализовать стандартный Comparable
интерфейс, но этот способ сравнения не полагаться на самоанализ и импорт BeanUtil кажется очень бесполезно...
Итак, как правильно его использовать?
Я, наконец, сдался и закодировал это. Это не отвечает на вопрос, но это мой способ решить эту проблему:
import org.apache.commons.beanutils.BeanUtils;
public static void assertBeansEqual(final Object expected, final Object given) {
try {
final Map<String, String> expectedDescription = BeanUtils.describe(expected);
final Map<String, String> givenDescription = BeanUtils.describe(given);
// if the two bean don't share the same attributes.
if (!(expectedDescription.keySet().containsAll(givenDescription.keySet()))) {
final Set<String> keySet = givenDescription.keySet();
keySet.removeAll(expectedDescription.keySet());
fail("The expected bean has not the same attributes than the given bean, the followings fields are not present in the expected bean :" + keySet);
}
if (!(givenDescription.keySet().containsAll(expectedDescription.keySet()))) {
final Set<String> keySet = expectedDescription.keySet();
keySet.removeAll(givenDescription.keySet());
fail("The expected bean has not the same attributes than the given bean, the followings fields are not present in the given bean :" + keySet);
}
final List<String> differences = new LinkedList<String>();
for (final String key : expectedDescription.keySet()) {
if (isNull(expectedDescription.get(key))) {
// if the bean1 value is null and not the other -> not equal. This test is
// required to avoid NPE attributes values are null. (null object dot not have
// equals method).
if (!isNull(givenDescription.get(key))) {
differences.add(key);
}
}
else {
// if two attributes don't share an attributes value.
if (!expectedDescription.get(key).equals(givenDescription.get(key))) {
differences.add(key);
}
}
}
if (!differences.isEmpty()) {
String attributes = "";
for (final String attr : differences) {
attributes = attributes + "|" + attr;
}
fail("Assertion fail, the expected bean and the given bean attributes values differ for the followings attributes : " + attributes + "|");
}
}
catch (final Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
}
Вы должны посмотреть на различные конструкторы:
BeanComparator (свойство String)
BeanComparator (свойство String, компаратор компаратора)
Здесь бывший javadoc (второй пара - ваш ответ):
Создает компаратор на основе свойств для bean-компонентов. Это сравнивает два компонента по свойству, указанному в параметре свойства. Этот конструктор создает BeanComparator, который использует ComparableComparator для сравнения значений свойств.
Передача "null" этому конструктору приведет к тому, что BeanComparator будет сравнивать объекты на основе естественного порядка, то есть java.lang.Comparable.
Как и следовало ожидать, конструктор, который вы вызываете, выполняет именно это:
this(null);
Для сравнения нескольких свойств вы можете использовать второй вариант
Collections.sort(collection,
new BeanComparator("property1",
new BeanComparator("property2",
new BeanComparator("property3"))));
Я лично почувствовал, что Apache Commons CompareToBuilder
и Google Guavas ComparisonChain
- лучший выбор.
compareToBuilde
иcomparisonChain
они позволяют автообновления боба comprarison?compareTo
метод, так же , какEqualsBuilder
поможет вам построитьequals
метод. Не самое большое преимущество, с которым я согласен, но необходимость указывать имена параметров (возможно, потому что он использует отражение под капотом) вBeanComparator
не устраивает меня.