public class Equals extends Object
Object.equals(Object) of a class.
The aim of this class, paired with the class Hashcode, is to avoid the boilerplate code
needed to implement the Object.equals(Object) method and to provide an implementation
that is consistent with the related Object.hashCode() method.
Even if most of the IDEs provide tools to generate implementations of Object.hashCode()
and Object.equals(Object), the generated code is ugly and hard to understand.
By using this utility class the resulting Object.equals(Object) method will be small,
clean and easy to read.
You may have seen a lot of times implementation of the method Object.equals(Object)
in this form:
public boolean equals( Object obj )
{
if( obj == this )
return true;
if( getClass() != obj.getClass() )
return false;
ThisClass other = (ThisClass) obj;
if( field == null )
{
if( other.field != null )
return false;
} else if( ! field.equals(other.field) )
return false;
if( array == null )
return other.array == null;
else if( other.array == null )
return false;
if( array.length != other.array.length )
return false;
for( int i=0; i<array.length; i++ )
{
Object o1 = array[i];
Object o2 = other.array[i];
boolean e = o1==null ? o2==null : o1.equals( o2 );
if( ! e )
return false;
}
return true;
}
It is quite hard to understand and definitely ugly!
With this utility you can get the same result with a single instruction:
public boolean equals( Object other )
{
return Equals.ifSameClass(
this, other,
o -> o.field,
o -> o.array
);
}
Much better!
Important: This class can be used also to compare two objects as follows:
if( Equals.ifSameClass(anObject,anotherObject) )
// Do something...
but the result may not be what expected.
Since this class is intended to be used inside Object.equals(Object) none of its methods
invokes Object.equals(Object) on the provided objects, otherwise it will generate an
invocation loop and a StackOverflowError will be thrown.
So the method Equals.ifSameClass( anObject, anotherObject ) will return true
if anObject and anotherObject are both null or if are both not
null and belong to the same class, but invoking anObject.equals(anotherObject)
on the same instances could return false.
There are cases where you may want to consider two objects to be equal if both implement the same interface, and they behave in the same way in relation to the interface specifications.
A well known example of this case are the java native implementations of
the Collection interface. If you take a look into
AbstractList.equals(Object) you will see something like this:
public boolean equals( Object o )
{
if( o == this )
return true;
if( ! (o instanceof List) )
return false;
ListIterator<E> e1 = listIterator();
ListIterator<?> e2 = ((List<?>) o).listIterator();
while( e1.hasNext() && e2.hasNext() )
{
E o1 = e1.next();
Object o2 = e2.next();
if( !(o1==null ? o2==null : o1.equals(o2)) )
return false;
}
return !(e1.hasNext() || e2.hasNext());
}
As you can see, an object is considered to be equal to
the current list if it implements List
and if the elements in the same position are equal as well.
The same result can be achieved using this utility like this:
public boolean equals( Object other )
{
return Equals.ifInstancesOf( List.class, this, other, ( l1, l2 ) ->
{
ListIterator<?> e1 = l1.listIterator();
ListIterator<?> e2 = l2.listIterator();
while( e1.hasNext() && e2.hasNext() )
{
Object o1 = e1.next();
Object o2 = e2.next();
if( !(o1==null ? o2==null : o1.equals(o2)) )
return false;
}
return !(e1.hasNext() || e2.hasNext());
}
}
| Modifier and Type | Method and Description |
|---|---|
static <T> boolean |
ifInstancesOf(Class<T> type,
Object thisObj,
Object otherObj,
BiFunction<T,T,Boolean> check)
This method is intended to be used inside a
Object.equals(Object)
method, to check if the object to compare is not null and if both
objects are instances of the given type. |
static <T> boolean |
ifSameClass(T thisObj,
Object otherObj,
Function<T,Object>... fields)
This method is intended to be used inside a
Object.equals(Object)
method, to check if the object to compare is not null and if it has
the same class as this object. |
@SafeVarargs public static <T> boolean ifSameClass(T thisObj, Object otherObj, Function<T,Object>... fields)
Object.equals(Object)
method, to check if the object to compare is not null and if it has
the same class as this object.
If the previous condition holds then a field by field check will be performed
using the provided Functions to extract the values to compare.
If one of the fields to compare is an array, the deep equality of the Arrays
facility will be used. It performs a deep equality check to be consistent with the
java native implementations of Collection.equals(Object).
T - the returned type.thisObj - the object owner of the method Object.equals(Object).otherObj - the object to compare.fields - a list of functions that get the field to compare from the given object.otherObj casted to the right class if possible, null otherwise.public static <T> boolean ifInstancesOf(Class<T> type, Object thisObj, Object otherObj, BiFunction<T,T,Boolean> check)
Object.equals(Object)
method, to check if the object to compare is not null and if both
objects are instances of the given type.
If the previous condition holds then a custom check will be performed
using the provided BiFunction.
This method is useful in those cases where two objects implement the same interface and are considered equals if behave in the same way in relation to the interface specifications.
A well known example of this case are the java native implementations of
the Collection interface. If you take a look into
AbstractList.equals(Object) you will see that another
object is considered to be equal if implements List
and elements in the same position are equal. A similar implementation is
can be found in AbstractSet.equals(Object).
T - the type to be implemented by both objects.type - class representing the type to be implemented by both objects.thisObj - the object owner of the method Object.equals(Object).otherObj - the object to compare.check - the actual implementation of the logic needed to check the equality.otherObj casted to the right class if possible, null otherwise.Copyright © 2011–2020 Nerd4j. All rights reserved.