Assert that two java beans are equivalent - java

This question is close, but still not what I want. I'd like to assert in a generic way that two bean objects are equivalent. In case they are not, I'd like a detailed error message explaining the difference instead of a boolean "equal" or "not equal".

import static org.hamcrest.beans.SamePropertyValuesAs.samePropertyValuesAs;
import static org.junit.Assert.assertThat;
#Test
public void beansAreTheSame(){
MyDomianClass bean1 = new MyDomainClass();
MyDomianClass bean2 = new MyDomainClass();
//TODO - some more test logic
assertThat(bean1, samePropertyValuesAs(bean2));
}

I recommend you use unitils library:
http://www.unitils.org/tutorial-reflectionassert.html
public class User {
private long id;
private String first;
private String last;
public User(long id, String first, String last) {
this.id = id;
this.first = first;
this.last = last;
}
}
User user1 = new User(1, "John", "Doe");
User user2 = new User(1, "John", "Doe");
assertReflectionEquals(user1, user2);
See also:
Is there a Java reflection utility to do a deep comparison of two objects?
NUnit - Assert to check all properties are equal?

You can use Commons Lang's ToStringBuilder to convert both of them into readable strings and then use assertEquals() on both strings.
If you like XML, you can use java.lang.XMLEncoder to turn your bean into XML and then compare the two XML documents.
Personally, I prefer ToStringBuilder since it gives you more control over the formatting and allows you to do things like sorting the elements in a set to avoid false negatives.
I suggest to put each field of the bean in a different line to make it much more simple to compare them (see my blog for details).

You can set all fields like this:
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;
import static org.hamcrest.Matchers.is;
#Test
public void test_returnBean(){
arrange();
MyBean myBean = act();
assertThat(myBean, allOf(hasProperty("id", is(7L)),
hasProperty("name", is("testName1")),
hasProperty("description", is("testDesc1"))));
}

I think, the most generic approach is to reflect the bean members and test them for equality one-by-one. The common lang's EqualsBuilder is a good start and it should be not a big deal, to adapt it (on source level) to your requirements (reporting the differences instead of returning the equals result).

For unit testing this can be done with JUnit and Mockito using ReflectionEquals. When implementing in the following manner, it will dump the JSON representations of the objects when any fields are not equal which makes it easy to find the offending difference.
import static org.junit.Assert.assertThat;
import org.mockito.internal.matchers.apachecommons.ReflectionEquals;
assertThat("Validating field equivalence of objects", expectedObjectValues, new ReflectionEquals(actualObjectValues));

Since you didn't like the answers in the question you referenced, why not just have a toXml method in each bean, turn them into an xml file and then use xmlUnit to compare.
You can get more info on comparing xml files here:
Best way to compare 2 XML documents in Java

You're not really asserting equality, more doing a "diff". Clearly, the meaning of "same" depends upon particular logic for each type, and the representation of the difference also may vary. One major difference between this requirment and a conventional equals() is that usually equals() will stop as soon as the first difference is seen, you will want to carry on and compare every field.
I would look at reusing some of the equals() patterns, but I suspect you'll need to write your own code.

I am assuming here that both beans are of the same type, in which case only the member variable values will differ across bean instances.
Define an util class (public static final with private ctor) called, say, BeanAssertEquals. Use Java reflection to obtain the value of each member variable in each bean. Then do an equals() between values for the same member variable in different beans. If an equality fails, mention the field name.
Note: member variables are usually private, so you would need to use reflection to temporarily change the accessibility of private members.
Additionally, depending how fine-grained you want the assertion to work, you should consider the following:
Equality of member variables not in the bean class but all superclasses.
Equality of elements in arrays, in case a member variable is of type array.
For two values of a given member across beans, you might consider doing BeanAssertEquals.assertEquals(value1, value2) instead of value1.equals(value2).

(to build on my comment to Andreas_D above)
/** Asserts two objects are equals using a reflective equals.
*
* #param message The message to display.
* #param expected The expected result.
* #param actual The actual result
*/
public static void assertReflectiveEquals(final String message,
final Object expected, final Object actual) {
if (!EqualsBuilder.reflectionEquals(expected, actual)) {
assertEquals(message,
reflectionToString(expected, ToStringStyle.SHORT_PREFIX_STYLE),
reflectionToString(actual, ToStringStyle.SHORT_PREFIX_STYLE));
fail(message + "expected: <" + expected + "> actual: <" + actual + ">");
}
}
This is what I use, and I believe it meets all basic requirements. By doing the assert on the reflective ToString then Eclipse will highlight the difference.
While Hamcrest can offer a much nicer message, this does involve a good deal less code.

The first quesion I'd have to ask if is, do you want to do 'deep' equals on the Bean? does it have child beans that need to be tested? You can override the equals method, but this only returns a boolean, so you could create a 'comparator' and that could throw an exception with a message about what was not equal.
In the following examples, I've listed a few ways to implement the equals method.
if you want to check if they are the same object instance, then the normal equals method from Object will tell you.
objectA.equals(objectB);
if you want to write a customer equals method to check that all the member varibles of an object make them equal then you can override the equals method like this...
/**
* Method to check the following...
* <br>
* <ul>
* <li>getTitle</li>
* <li>getInitials</li>
* <li>getForename</li>
* <li>getSurname</li>
* <li>getSurnamePrefix</li>
* </ul>
*
* #see java.lang.Object#equals(java.lang.Object)
*/
#Override
public boolean equals(Object obj)
{
if ( (!compare(((ICustomer) obj).getTitle(), this.getTitle()))
|| (!compare(((ICustomer) obj).getInitials(), this.getInitials()))
|| (!compare(((ICustomer) obj).getForename(), this.getForename()))
|| (!compare(((ICustomer) obj).getSurname(), this.getSurname()))
|| (!compare(((ICustomer) obj).getSurnamePrefix(), this.getSurnamePrefix()))
|| (!compare(((ICustomer) obj).getSalutation(), this.getSalutation())) ){
return false;
}
return true;
}
The last option is to use java reflection to check all the member varibles in the equals method. This is great if you really want to check every member varible via its bean get/set method. It wont (I dont think) allow you to check private memeber varibles when testing of the two objects are the same. (not if your object model has a circular dependancy, dont do this, it will never return)
NOTE: this is not my code, it comes from...
Java Reflection equals
public static boolean equals(Object bean1, Object bean2)
{
// Handle the trivial cases
if (bean1 == bean2)
return true;
if (bean1 == null)
return false;
if (bean2 == null)
return false;
// Get the class of one of the parameters
Class clazz = bean1.getClass();
// Make sure bean1 and bean2 are the same class
if (!clazz.equals(bean2.getClass()))
{
return false;
}
// Iterate through each field looking for differences
Field[] fields = clazz.getDeclaredFields();
for (int i = 0; i < fields.length; i++)
{
// setAccessible is great (encapsulation
// purists will disagree), setting to true
// allows reflection to have access to
// private members.
fields[i].setAccessible(true);
try
{
Object value1 = fields[i].get(bean1);
Object value2 = fields[i].get(bean2);
if ((value1 == null && value2 != null) ||
(value1 != null && value2 == null))
{
return false;
}
if (value1 != null &&
value2 != null &&
!value1.equals(value2))
{
return false;
}
}
catch (IllegalArgumentException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
}
return true;
The one thing that this does not do it to tell you the reason for the difference, but that could be done via message to Log4J when you find a section that is not equal.

The xtendbeans library could be of interest in this context:
AssertBeans.assertEqualBeans(expectedBean, actualBean);
This produces a JUnit ComparisonFailure à la:
expected:
new Person => [
firstName = 'Homer'
lastName = 'Simpson'
address = new Address => [
street = '742 Evergreen Terrace'
city = 'SpringField'
]
]
but was:
new Person => [
firstName = 'Marge'
lastName = 'Simpson'
address = new Address => [
street = '742 Evergreen Terrace Road'
city = 'SpringField'
]
]
You could also use it just to get the textual representation for other purposes:
String beanAsLiteralText = new XtendBeanGenerator().getExpression(yourBean)
With this library you can use the above syntactically valid object initialization code fragment to copy/paste it into a (Xtend) source class for the expectedBean, but you don't not have to, it can perfectly well be used without Xtend as well.

Related

What is a good design pattern for tracking issues in a class?

I have a class that has a custom equals() method. When I compare two objects using this equals method, not only am I interested in whether or not they are equal, but if they are not equal, what was different about them. Finally, I want to be able to retrieve the differences arising from an unequal situation.
I currently use logging to display where my objects are unequal. This works, but I have a new requirement of being able to extract the actual results of the equals check for display later. I suspect there is an object-oriented design pattern for handling this type of situation.
public class MyClass {
int x;
public boolean equals(Object obj) {
// make sure obj is instance of MyClass
MyClass that = (MyClass)obj;
if(this.x != that.x) {
// issue that I would like to store and reference later, after I call equals
System.out.println("this.x = " + this.x);
System.out.println("that.x = " + that.x);
return false;
} else {
// assume equality
return true
}
}
}
Are there any good design pattern suggestions where some sort of work is being done, but a secondary object collects information about how well that work was done which can later be retrieved and displayed?
Your problem is that you are trying to use the boolean equals(Object) API for something it was not designed for. I don't think there is any design pattern that will allow you to do this.
Instead, you should be doing something like this:
public class Difference {
private Object thisObject;
private Object otherObject;
String difference;
...
}
public interface Differenceable {
/** Report the differences between 'this' and 'other'. ... **/
public List<Difference> differences(Object other);
}
Then implement this for all classes where you want "differenceable" functionality. For example:
public class MyClass implements Differenceable {
int x;
...
public List<Difference> differences(Object obj) {
List<Difference> diffs = new ArrayList<>();
if (!(obj instanceof MyClass)) {
diffs.add(new Difference<>(this, obj, "types differ");
} else {
MyClass other = (MyClass) obj;
if (this.x != other.x) {
diffs.add(new Difference<>(this, obj, "field 'x' differs");
}
// If fields of 'this' are themselves differenceable, you could
// recurse and then merge the result lists into 'diffs'.
}
return diffs;
}
}
I am unaware of a particular design pattern for this. One problem with this requirement is that to find out all differences between two unequal objects you would need to continue additional comparisons after the first false result (which is typically not necessary).
If I were doing this I might consider doing a normal equality test and if not equal, kick off a thread to determine why and log the results rather than incorporate such logic in the equals method itself. This might be done in a special method outside of the equals method.

What is a 'canonical representation' of a field meant to be for equals() method (Joshua Bloch)

In chapter 3, item 8:
public final class CaseInsensitiveString {
private final String s;
public CaseInsensitiveString(String s) {
if (s == null)
throw new NullPointerException();
this.s = s;
}
#Override public boolean equals(Object o) {
return o instanceof CaseInsensitiveString &&
((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
}
// remainder omitted
}
After describing issues surrounding the equals() method, he goes on to talk about this class in the context of comparing fields.
For some classes, such as CaseInsensitiveString above, field comparisons are more complex than simple equality tests. If this is the case, you may want to store a canonical form of the field, so the equals() method can do cheap exact comparisons on these canonical forms rather than more costly inexact comparisons. This technique is most appropriate for immutable classes; if the object can change, you must keep the canonical form up-to-date.
So my question (and I double-checked what 'canonical' means): what is Bloch talking about? What would the canonical form be? I'm ready to be told that the answer is very simple (presumably otherwise his editor would have told him to add more) but I want to see other people say so.
He also mentions the same thing for hashCode() in the next item 9.
To give it in context, he also discusses a bad version of the equals() method for CaseInsensitiveString:
// Broken - violates symmetry
#Override public boolean equals(Object o) {
if (o instanceof CaseInsensitiveString)
return s.equalsIgnoreCase(
((CaseInsensitiveString) o).s);
if (o instanceof String) // one-way interoperability!
return s.equalsIgnoreCase((String) o);
return false;
}
You should add another final field and store value s.toUpperCase() for it.
This new field will be canonical representation s field. New implementation of method equals() (see code bellow) will be cheaper. This approach will work only for immutable classes.
Another point you should not forget override hashCode() if you override equals().
public final class CaseInsensitiveString {
private final String s;
private final String sForEquals; //field added for simplifier equals method
public CaseInsensitiveString(String s) {
if (s == null) {
throw new IllegalArgumentException(); //NullPointerException() - bad practice
}
this.s = s;
this.sForEquals = s.toUpperCase();
}
#Override
public boolean equals(Object o) {
return o instanceof CaseInsensitiveString &&
((CaseInsensitiveString) o).sForEquals.equals(this.sForEquals);
}
#Override
public int hashCode(){
return sForEquals.hashCode();
}
// remainder omitted
}
The term canonical has some different usages. It refers to values that have several representations (or maybe several varying values that are equal). Then often one specific representation (or value) is chosen as canonical one.
Example: Sets of integers: canonical { 2, 3, 5 } = { 3, 5, 2 } = { 2, 2, 5, 3 } = .... .
For the plain java String there is as issue too. The same text in Unicode can be represented differently: ĉ either as one code point "\u0109"SMALL-LETTER-C-WITH-CIRCUMFLEX, or as two code points c SMALL-LETTER-C and a zero-width ^ COMBINED-DIACRITICAL-MARK-CIRCUMFLEX ("\u0063\u0302").
So even a plain String should be canonicalized in some cases:
String s = "...";
String s1 = Normalizer.normalize(s, Normalizer.Form.NFKD);
This uses Normalizer to decompose a string. This has the advantage, that one could sort and "c" and "ĉ" stay together. One could remove the combining diacritical marks with a regex and would have an ASCII version.
In fact different operating systems handle Unicode names differently, and not always version control systems respect a cross-platform canonicalisation.
Only after a Normalizer.normalize a comparison with String.equals indeed indicates Unicode text equality.
Your question had two parts:
Canonical form means "standardised form - in this case a lowercase version of the field, used for comparison. Every time the value changes, the lowercase copy would have to be updated, so there's an overhead to this design choice. Further, this idea is an optimization for performance only, and frankly is not recommended as it's "premature optimisation"
Non symmetry of equals allows code such that a.equals(b) but not b.equals(a), thus violating the equals contract. In your example, it's possible for a String to be equal to an instance of your class, because its equals() method allows that, but the implementation of equals() in the String class does not allow for an instance of your class to be considered as equal to a String.

How do I define a method once and use it as a "building plan" for other methods?

I'm new to Java and have the following question:
Is there an easier way of making methods for each variable?
The meaning behind the question is:
Do I have to define a method that does the exact same thing as other methods except that they use different variable names and types?
I think the most common methods with the same problem are the get- and set-accessors:
They share the same structure, the only difference are the variable types and names.
In my following example, you need to know:
Variables varA-varD just represent the existance of multiple variables with various types and names.
The variable "inheritor" is special. I do NOT implement inheritance, but I DO have to verify that somewhere, maybe in the inheritor of the inheritor of the inheritor the same variable
has a value ("!= null"; in case of Lists, HashMaps, Enumerations, etc.)
or
has a value other than -2 (because 0 means nothing and -1 indicates "infinite" in my system, so I thought using -2 for indicating that the variable hasn't been set yet is a good idea; in case of Integers, Floats, Doubles, etc.).
I have verification methods...
...to check whether the variables have already been set (or not)
and for this reason the code is located
...outside of the setter because I have to check the variables even when they have not been set yet.
public class ExampleClass {
private int varA;
private String varB;
private ExampleEnum varC;
private List<OtherClass> varD;
//there are more variables here...
private ExampleClass inheritor;
public int getVarA() {
return varA;
}
public void setVarA(int varA) {
this.varA = varA;
}
public boolean validateVarA() {
//-2 is "not set" for Integers
if (varA == -2 && inheritor != null) {
return inheritor.getVarA() != -2;
} else {
return varA != -2;
}
}
//Do I have to define three methods for each variable?
//What if I had like 20 variables?!?
//I would need 60 methods altough every third one
//shares the same structure.
}
I needed some sort of "building plan" for a method:
public T getVar() {
return var;
}
public void setVar(T var) {
this.var = var;
}
public boolean verifyVar() {
//How would I get the invalid value for each type?
T invalidValue = ?;
if (var == invalidValue && inheritor != null) {
return inheritor.getVar() != invalidValue;
} else {
return var != invalidValue;
}
}
In the example above:
"Var" or "var" would be the variable name
and
"T" would be the type of var
I have no idea how I would get the invalid value...
Sorry in case I think too complicated and there is a simple answer to my question. Furthermore, I apologize for any grammar mistakes that may occur.
For generic getters and setters, there's always Map<String, Object>, but I'm pretty sure that's not what you want, so you should stick to the JavaBean conventions (as mentioned in the comments, any IDE would generate those for you and it makes total sense to have them according to OOP recommendations).
Any attempt to implement generic accessors would sooner or later become some java.util.Map with tones of reflection around it. If that's what you want, perhaps you should reconsider your model and switch your type-safe beans to some free-form types like map.
For validation, there's the javax.validation package (JSR-303).

Is there a Java utility to do a deep comparison of two objects? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 2 years ago.
Improve this question
How to "deep"-compare two objects that do not implement the equals method based on their field values in a test?
Original Question (closed because lack of precision and thus not fulfilling SO standards), kept for documentation purposes:
I'm trying to write unit tests for a variety of clone() operations inside a large project and I'm wondering if there is an existing class somewhere that is capable of taking two objects of the same type, doing a deep comparison, and saying if they're identical or not?
Unitils has this functionality:
Equality assertion through reflection, with different options like ignoring Java default/null values and ignoring order of collections
I love this question! Mainly because it is hardly ever answered or answered badly. It's like nobody has figured it out yet. Virgin territory :)
First off, don't even think about using equals. The contract of equals, as defined in the javadoc, is an equivalence relation (reflexive, symmetric, and transitive), not an equality relation. For that, it would also have to be antisymmetric. The only implementation of equals that is (or ever could be) a true equality relation is the one in java.lang.Object. Even if you did use equals to compare everything in the graph, the risk of breaking the contract is quite high. As Josh Bloch pointed out in Effective Java, the contract of equals is very easy to break:
"There is simply no way to extend an instantiable class and add an aspect while preserving the equals contract"
Besides what good does a boolean method really do you anyway? It'd be nice to actually encapsulate all the differences between the original and the clone, don't you think? Also, I'll assume here that you don't want to be bothered with writing/maintaining comparison code for each object in the graph, but rather you're looking for something that will scale with the source as it changes over time.
Soooo, what you really want is some kind of state comparison tool. How that tool is implemented is really dependent on the nature of your domain model and your performance restrictions. In my experience, there is no generic magic bullet. And it will be slow over a large number of iterations. But for testing the completeness of a clone operation, it'll do the job pretty well. Your two best options are serialization and reflection.
Some issues you will encounter:
Collection order: Should two collections be considered similar if they hold the same objects, but in a different order?
Which fields to ignore: Transient? Static?
Type equivalence: Should field values be of exactly the same type? Or is it ok for one to extend the other?
There's more, but I forget...
XStream is pretty fast and combined with XMLUnit will do the job in just a few lines of code. XMLUnit is nice because it can report all the differences, or just stop at the first one it finds. And its output includes the xpath to the differing nodes, which is nice. By default it doesn't allow unordered collections, but it can be configured to do so. Injecting a special difference handler (Called a DifferenceListener) allows you to specify the way you want to deal with differences, including ignoring order. However, as soon as you want to do anything beyond the simplest customization, it becomes difficult to write and the details tend to be tied down to a specific domain object.
My personal preference is to use reflection to cycle through all the declared fields and drill down into each one, tracking differences as I go. Word of warning: Don't use recursion unless you like stack overflow exceptions. Keep things in scope with a stack (use a LinkedList or something). I usually ignore transient and static fields, and I skip object pairs that I've already compared, so I don't end up in infinite loops if someone decided to write self-referential code (However, I always compare primitive wrappers no matter what, since the same object refs are often reused). You can configure things up front to ignore collection ordering and to ignore special types or fields, but I like to define my state comparison policies on the fields themselves via annotations. This, IMHO, is exactly what annotations were meant for, to make meta data about the class available at runtime. Something like:
#StatePolicy(unordered=true, ignore=false, exactTypesOnly=true)
private List<StringyThing> _mylist;
I think this is actually a really hard problem, but totally solvable! And once you have something that works for you, it is really, really, handy :)
So, good luck. And if you come up with something that's just pure genius, don't forget to share!
In AssertJ, you can do:
Assertions.assertThat(expectedObject).isEqualToComparingFieldByFieldRecursively(actualObject);
Probably it won't work in all cases, however it will work in more cases that you'd think.
Here's what the documentation says:
Assert that the object under test (actual) is equal to the given
object based on recursive a property/field by property/field
comparison (including inherited ones). This can be useful if actual's
equals implementation does not suit you. The recursive property/field
comparison is not applied on fields having a custom equals
implementation, i.e. the overridden equals method will be used instead
of a field by field comparison.
The recursive comparison handles cycles. By default floats are
compared with a precision of 1.0E-6 and doubles with 1.0E-15.
You can specify a custom comparator per (nested) fields or type with
respectively usingComparatorForFields(Comparator, String...) and
usingComparatorForType(Comparator, Class).
The objects to compare can be of different types but must have the
same properties/fields. For example if actual object has a name String
field, it is expected the other object to also have one. If an object
has a field and a property with the same name, the property value will
be used over the field.
Override The equals() Method
You can simply override the equals() method of the class using the EqualsBuilder.reflectionEquals() as explained here:
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}
Just had to implement comparison of two entity instances revised by Hibernate Envers. I started writing my own differ but then found the following framework.
https://github.com/SQiShER/java-object-diff
You can compare two objects of the same type and it will show changes, additions and removals. If there are no changes, then the objects are equal (in theory). Annotations are provided for getters that should be ignored during the check. The frame work has far wider applications than equality checking, i.e. I am using to generate a change-log.
Its performance is OK, when comparing JPA entities, be sure to detach them from the entity manager first.
I am usin XStream:
/**
* #see java.lang.Object#equals(java.lang.Object)
*/
#Override
public boolean equals(Object o) {
XStream xstream = new XStream();
String oxml = xstream.toXML(o);
String myxml = xstream.toXML(this);
return myxml.equals(oxml);
}
/**
* #see java.lang.Object#hashCode()
*/
#Override
public int hashCode() {
XStream xstream = new XStream();
String myxml = xstream.toXML(this);
return myxml.hashCode();
}
http://www.unitils.org/tutorial-reflectionassert.html
public class User {
private long id;
private String first;
private String last;
public User(long id, String first, String last) {
this.id = id;
this.first = first;
this.last = last;
}
}
User user1 = new User(1, "John", "Doe");
User user2 = new User(1, "John", "Doe");
assertReflectionEquals(user1, user2);
Hamcrest has the Matcher samePropertyValuesAs. But it relies on the JavaBeans Convention (uses getters and setters). Should the objects that are to be compared not have getters and setters for their attributes, this will not work.
import static org.hamcrest.beans.SamePropertyValuesAs.samePropertyValuesAs;
import static org.junit.Assert.assertThat;
import org.junit.Test;
public class UserTest {
#Test
public void asfd() {
User user1 = new User(1, "John", "Doe");
User user2 = new User(1, "John", "Doe");
assertThat(user1, samePropertyValuesAs(user2)); // all good
user2 = new User(1, "John", "Do");
assertThat(user1, samePropertyValuesAs(user2)); // will fail
}
}
The user bean - with getters and setters
public class User {
private long id;
private String first;
private String last;
public User(long id, String first, String last) {
this.id = id;
this.first = first;
this.last = last;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirst() {
return first;
}
public void setFirst(String first) {
this.first = first;
}
public String getLast() {
return last;
}
public void setLast(String last) {
this.last = last;
}
}
If your objects implement Serializable you can use this:
public static boolean deepCompare(Object o1, Object o2) {
try {
ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
ObjectOutputStream oos1 = new ObjectOutputStream(baos1);
oos1.writeObject(o1);
oos1.close();
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
ObjectOutputStream oos2 = new ObjectOutputStream(baos2);
oos2.writeObject(o2);
oos2.close();
return Arrays.equals(baos1.toByteArray(), baos2.toByteArray());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Your Linked List example is not that difficult to handle. As the code traverses the two object graphs, it places visited objects in a Set or Map. Before traversing into another object reference, this set is tested to see if the object has already been traversed. If so, no need to go further.
I agree with the person above who said use a LinkedList (like a Stack but without synchronized methods on it, so it is faster). Traversing the object graph using a Stack, while using reflection to get each field, is the ideal solution. Written once, this "external" equals() and "external" hashCode() is what all equals() and hashCode() methods should call. Never again do you need a customer equals() method.
I wrote a bit of code that traverses a complete object graph, listed over at Google Code. See json-io (http://code.google.com/p/json-io/). It serializes a Java object graph into JSON and deserialized from it. It handles all Java objects, with or without public constructors, Serializeable or not Serializable, etc. This same traversal code will be the basis for the external "equals()" and external "hashcode()" implementation. Btw, the JsonReader / JsonWriter (json-io) is usually faster than the built-in ObjectInputStream / ObjectOutputStream.
This JsonReader / JsonWriter could be used for comparison, but it will not help with hashcode. If you want a universal hashcode() and equals(), it needs it's own code. I may be able to pull this off with a generic graph visitor. We'll see.
Other considerations - static fields - that's easy - they can be skipped because all equals() instances would have the same value for static fields, as the static fields is shared across all instances.
As for transient fields - that will be a selectable option. Sometimes you may want transients to count other times not. "Sometimes you feel like a nut, sometimes you don't."
Check back to the json-io project (for my other projects) and you will find the external equals() / hashcode() project. I don't have a name for it yet, but it will be obvious.
I think the easiest solution inspired by Ray Hulha solution is to serialize the object and then deep compare the raw result.
The serialization could be either byte, json, xml or simple toString etc. ToString seems to be cheaper. Lombok generates free easy customizable ToSTring for us. See example below.
#ToString #Getter #Setter
class foo{
boolean foo1;
String foo2;
public boolean deepCompare(Object other) { //for cohesiveness
return other != null && this.toString().equals(other.toString());
}
}
I guess you know this, but In theory, you're supposed to always override .equals to assert that two objects are truly equal. This would imply that they check the overridden .equals methods on their members.
This kind of thing is why .equals is defined in Object.
If this were done consistently you wouldn't have a problem.
A halting guarantee for such a deep comparison might be a problem. What should the following do? (If you implement such a comparator, this would make a good unit test.)
LinkedListNode a = new LinkedListNode();
a.next = a;
LinkedListNode b = new LinkedListNode();
b.next = b;
System.out.println(DeepCompare(a, b));
Here's another:
LinkedListNode c = new LinkedListNode();
LinkedListNode d = new LinkedListNode();
c.next = d;
d.next = c;
System.out.println(DeepCompare(c, d));
Apache gives you something, convert both objects to string and compare strings, but you have to Override toString()
obj1.toString().equals(obj2.toString())
Override toString()
If all fields are primitive types :
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
#Override
public String toString() {return
ReflectionToStringBuilder.toString(this);}
If you have non primitive fields and/or collection and/or map :
// Within class
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
#Override
public String toString() {return
ReflectionToStringBuilder.toString(this,new
MultipleRecursiveToStringStyle());}
// New class extended from Apache ToStringStyle
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.util.*;
public class MultipleRecursiveToStringStyle extends ToStringStyle {
private static final int INFINITE_DEPTH = -1;
private int maxDepth;
private int depth;
public MultipleRecursiveToStringStyle() {
this(INFINITE_DEPTH);
}
public MultipleRecursiveToStringStyle(int maxDepth) {
setUseShortClassName(true);
setUseIdentityHashCode(false);
this.maxDepth = maxDepth;
}
#Override
protected void appendDetail(StringBuffer buffer, String fieldName, Object value) {
if (value.getClass().getName().startsWith("java.lang.")
|| (maxDepth != INFINITE_DEPTH && depth >= maxDepth)) {
buffer.append(value);
} else {
depth++;
buffer.append(ReflectionToStringBuilder.toString(value, this));
depth--;
}
}
#Override
protected void appendDetail(StringBuffer buffer, String fieldName,
Collection<?> coll) {
for(Object value: coll){
if (value.getClass().getName().startsWith("java.lang.")
|| (maxDepth != INFINITE_DEPTH && depth >= maxDepth)) {
buffer.append(value);
} else {
depth++;
buffer.append(ReflectionToStringBuilder.toString(value, this));
depth--;
}
}
}
#Override
protected void appendDetail(StringBuffer buffer, String fieldName, Map<?, ?> map) {
for(Map.Entry<?,?> kvEntry: map.entrySet()){
Object value = kvEntry.getKey();
if (value.getClass().getName().startsWith("java.lang.")
|| (maxDepth != INFINITE_DEPTH && depth >= maxDepth)) {
buffer.append(value);
} else {
depth++;
buffer.append(ReflectionToStringBuilder.toString(value, this));
depth--;
}
value = kvEntry.getValue();
if (value.getClass().getName().startsWith("java.lang.")
|| (maxDepth != INFINITE_DEPTH && depth >= maxDepth)) {
buffer.append(value);
} else {
depth++;
buffer.append(ReflectionToStringBuilder.toString(value, this));
depth--;
}
}
}}

What are the alternatives to comparing the equality of two objects?

http://leepoint.net/notes-java/data/expressions/22compareobjects.html
It turns out that defining equals()
isn't trivial; in fact it's moderately
hard to get it right, especially in
the case of subclasses. The best
treatment of the issues is in
Horstmann's Core Java Vol 1.
If equals() must always be overridden, then what is a good approach for not being cornered into having to do object comparison? What are some good "design" alternatives?
EDIT:
I'm not sure this is coming across the way that I had intended. Maybe the question should be more along the lines of "Why would you want to compare two objects?" Based upon your answer to that question, is there an alternative solution to comparison? I don't mean, a different implementation of equals. I mean, not using equality at all. I think the key point is to start with that question, why would you want to compare two objects.
If equals() must always be overridden,
then what is a good approach for not
being cornered into having to do
object comparison?
You are mistaken. You should override equals as seldom as possible.
All this info comes from Effective Java, Second Edition (Josh Bloch). The first edition chapter on this is still available as a free download.
From Effective Java:
The easiest way to avoid problems is
not to override the equals method, in
which case each instance of the class
is equal only to itself.
The problem with arbitrarily overriding equals/hashCode is inheritance. Some equals implementations advocate testing it like this:
if (this.getClass() != other.getClass()) {
return false; //inequal
}
In fact, the Eclipse (3.4) Java editor does just this when you generate the method using the source tools. According to Bloch, this is a mistake as it violates the Liskov substitution principle.
From Effective Java:
There is no way to extend an
instantiable class and add a value
component while preserving the equals
contract.
Two ways to minimize equality problems are described in the Classes and Interfaces chapter:
Favour composition over inheritance
Design and document for inheritance or else prohibit it
As far as I can see, the only alternative is to test equality in a form external to the class, and how that would be performed would depend on the design of the type and the context you were trying to use it in.
For example, you might define an interface that documents how it was to be compared. In the code below, Service instances might be replaced at runtime with a newer version of the same class - in which case, having different ClassLoaders, equals comparisons would always return false, so overriding equals/hashCode would be redundant.
public class Services {
private static Map<String, Service> SERVICES = new HashMap<String, Service>();
static interface Service {
/** Services with the same name are considered equivalent */
public String getName();
}
public static synchronized void installService(Service service) {
SERVICES.put(service.getName(), service);
}
public static synchronized Service lookup(String name) {
return SERVICES.get(name);
}
}
"Why would you want to compare two objects?"
The obvious example is to test if two Strings are the same (or two Files, or URIs). For example, what if you wanted to build up a set of files to parse. By definition, the set contains only unique elements. Java's Set type relies on the equals/hashCode methods to enforce uniqueness of its elements.
I don't think it's true that equals should always be overridden. The rule as I understand it is that overriding equals is only meaningful in cases where you're clear on how to define semantically equivalent objects. In that case, you override hashCode() as well so that you don't have objects that you've defined as equivalent returning different hashcodes.
If you can't define meaningful equivalence, I don't see the benefit.
How about just do it right?
Here's my equals template which is knowledge applied from Effective Java by Josh Bloch. Read the book for more details:
#Override
public boolean equals(Object obj) {
if(this == obj) {
return true;
}
// only do this if you are a subclass and care about equals of parent
if(!super.equals(obj)) {
return false;
}
if(obj == null || getClass() != obj.getClass()) {
return false;
}
final YourTypeHere other = (YourTypeHere) obj;
if(!instanceMember1.equals(other.instanceMember1)) {
return false;
}
... rest of instanceMembers in same pattern as above....
return true;
}
Mmhh
In some scenarios you can make the object unmodifiable ( read-only ) and have it created from a single point ( a factory method )
If two objects with the same input data ( creation parameters ) are needed the factory will return the same instance ref and then using "==" would be enough.
This approach is useful under certain circumstances only. And most of the times would look overkill.
Take a look at this answer to know how to implement such a thing.
warning it is a lot of code
For short see how the wrapper class works since java 1.5
Integer a = Integer.valueOf( 2 );
Integer b = Integer.valueOf( 2 );
a == b
is true while
new Integer( 2 ) == new Integer( 2 )
is false.
It internally keeps the reference and return it if the input value is the same.
As you know Integer is read-only
Something similar happens with the String class from which that question was about.
Maybe I'm missing the point but the only reason to use equals as opposed to defining your own method with a different name is because many of the Collections (and probably other stuff in the JDK or whatever it's called these days) expect the equals method to define a coherent result. But beyond that, I can think of three kinds of comparisons that you want to do in equals:
The two objects really ARE the same instance. This makes no sense to use equals because you can use ==. Also, and correct me if I've forgotten how it works in Java, the default equals method does this using the automatically generated hash codes.
The two objects have references to the same instances, but are not the same instance. This is useful, uh, sometimes... particularly if they are persisted objects and refer to the same object in the DB. You would have to define your equals method to do this.
The two objects have references to objects that are equal in value, though they may or may not be the same instances (in other words, you compare values all the way through the hierarchy).
Why would you want to compare two objects? Well, if they're equal, you would want to do one thing, and if they're not, you would want to do something else.
That said, it depends on the case at hand.
The main reason to override equals() in most cases is to check for duplicates within certain Collections. For example, if you want to use a Set to contain an object you have created you need to override equals() and hashCode() within your object. The same applies if you want to use your custom object as a key in a Map.
This is critical as I have seen many people make the mistake in practice of adding their custom objects to Sets or Maps without overriding equals() and hashCode(). The reason this can be especially insidious is the compiler will not complain and you can end up with multiple objects that contain the same data but have different references in a Collection that does not allow duplicates.
For example if you had a simple bean called NameBean with a single String attribute 'name', you could construct two instances of NameBean (e.g. name1 and name2), each with the same 'name' attribute value (e.g. "Alice"). You could then add both name1 and name2 to a Set and the set would be size 2 rather than size 1 which is what is intended. Likewise if you have a Map such as Map in order to map the name bean to some other object, and you first mapped name1 to the string "first" and later mapped name2 to the string "second" you will have both key/value pairs in the map (e.g. name1->"first", name2->"second"). So when you do a map lookup it will return the value mapped to the exact reference you pass in, which is either name1, name2, or another reference with name "Alice" that will return null.
Here is a concrete example preceded by the output of running it:
Output:
Adding duplicates to a map (bad):
Result of map.get(bean1):first
Result of map.get(bean2):second
Result of map.get(new NameBean("Alice"): null
Adding duplicates to a map (good):
Result of map.get(bean1):second
Result of map.get(bean2):second
Result of map.get(new ImprovedNameBean("Alice"): second
Code:
// This bean cannot safely be used as a key in a Map
public class NameBean {
private String name;
public NameBean() {
}
public NameBean(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return name;
}
}
// This bean can safely be used as a key in a Map
public class ImprovedNameBean extends NameBean {
public ImprovedNameBean(String name) {
super(name);
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if(obj == null || getClass() != obj.getClass()) {
return false;
}
return this.getName().equals(((ImprovedNameBean)obj).getName());
}
#Override
public int hashCode() {
return getName().hashCode();
}
}
public class MapDuplicateTest {
public static void main(String[] args) {
MapDuplicateTest test = new MapDuplicateTest();
System.out.println("Adding duplicates to a map (bad):");
test.withDuplicates();
System.out.println("\nAdding duplicates to a map (good):");
test.withoutDuplicates();
}
public void withDuplicates() {
NameBean bean1 = new NameBean("Alice");
NameBean bean2 = new NameBean("Alice");
java.util.Map<NameBean, String> map
= new java.util.HashMap<NameBean, String>();
map.put(bean1, "first");
map.put(bean2, "second");
System.out.println("Result of map.get(bean1):"+map.get(bean1));
System.out.println("Result of map.get(bean2):"+map.get(bean2));
System.out.println("Result of map.get(new NameBean(\"Alice\"): "
+ map.get(new NameBean("Alice")));
}
public void withoutDuplicates() {
ImprovedNameBean bean1 = new ImprovedNameBean("Alice");
ImprovedNameBean bean2 = new ImprovedNameBean("Alice");
java.util.Map<ImprovedNameBean, String> map
= new java.util.HashMap<ImprovedNameBean, String>();
map.put(bean1, "first");
map.put(bean2, "second");
System.out.println("Result of map.get(bean1):"+map.get(bean1));
System.out.println("Result of map.get(bean2):"+map.get(bean2));
System.out.println("Result of map.get(new ImprovedNameBean(\"Alice\"): "
+ map.get(new ImprovedNameBean("Alice")));
}
}
Equality is fundamental to logic (see law of identity), and there's not much programming you can do without it. As for comparing instances of classes that you write, well that's up to you. If you need to be able to find them in collections or use them as keys in Maps, you'll need equality checks.
If you've written more than a few nontrivial libraries in Java, you'll know that equality is hard to get right, especially when the only tools in the chest are equals and hashCode. Equality ends up being tightly coupled with class hierarchies, which makes for brittle code. What's more, no type checking is provided since these methods just take parameters of type Object.
There's a way of making equality checking (and hashing) a lot less error-prone and more type-safe. In the Functional Java library, you'll find Equal<A> (and a corresponding Hash<A>) where equality is decoupled into a single class. It has methods for composing Equal instances for your classes from existing instances, as well as wrappers for Collections, Iterables, HashMap, and HashSet, that use Equal<A> and Hash<A> instead of equals and hashCode.
What's best about this approach is that you can never forget to write equals and hash method when they are called for. The type system will help you remember.

Categories

Resources