I'm trying to override equals
method for a parameterized class.
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Tuple))
return false;
Tuple<E> other = (Tuple<E>) obj; //unchecked cast
if (!a0.equals(other.a0) && !a0.equals(other.a1)) {
return false;
}
if (!a1.equals(other.a1) && !a1.equals(other.a0)) {
return false;
}
return true;
}
How can I make sure that <E>
of the other
object is the same as this
?
Parameter: This method accepts a mandatory parameter obj which is the object to be compared. Return Value: The method return true if Method object is same as passed object as parameter, otherwise false.
You can override the equals method on a record, if you want a behavior other than the default. But if you do override equals , be sure to override hashCode for consistent logic, as you would for a conventional Java class.
We can override the equals method in our class to check whether two objects have same data or not.
"If two objects are equal using Object class equals method, then the hashcode method should give the same value for these two objects." So, if in our class we override equals() we should override hashcode() method also to follow this rule.
You can do it by retaining a reference to Class<E>
type. However, in my opinion, equality tests should be about the values the objects represent rather than the concrete types the values get expressed.
A classic example of this is the Collections API for example. new ArrayList<String>().equals(new LinkedList<Object>())
returns true
. While these have completely different types, they represent the same value, namely "an empty collection".
Personally, should two Tuple
s that represent the same data (e.g. ("a", "b")
) be not equal, because one is of type Tuple<String>
while the other is Tuple<Object>
?
Because of erasure you can't. About the best you could do is store in the tuple class the type you plan for the Tuple to hold in a "java.lang.Class" field member. Then you could compare those fields to make sure the tuple class is holding the same types.
Also see this thread: What is the equivalent of the C++ Pair<L,R> in Java?
It would help if you post more about your class. I'm thinking the unchecked cast and your number of fields you equate means it should be Tuple<E,F> no?
EDIT: here is a useful Pair class I use regularly (you can adapt your Tuple class if needed). Note, similiar to suggestions by others this class just lets the contained members decide the question of equality. Your use case is what should determine whether equality is really based on the type of the contained members.
/**
* Adapted from http://forums.sun.com/thread.jspa?threadID=5132045
*
*
* @author Tim Harsch
*
* @param <L>
* @param <R>
*/
public class Pair<L, R> {
private final L left;
private final R right;
public R getRight() {
return right;
} // end getter
public L getLeft() {
return left;
} // end getter
public Pair(final L left, final R right) {
this.left = left;
this.right = right;
} // end constructor
public static <A, B> Pair<A, B> create(A left, B right) {
return new Pair<A, B>(left, right);
} // end factory method
@Override
public final boolean equals(Object o) {
if (!(o instanceof Pair<?,?>))
return false;
final Pair<?, ?> other = (Pair<?, ?>) o;
return equal(getLeft(), other.getLeft()) && equal(getRight(), other.getRight());
} // end method
public static final boolean equal(Object o1, Object o2) {
if (o1 == null) {
return o2 == null;
}
return o1.equals(o2);
} // end method
@Override
public int hashCode() {
int hLeft = getLeft() == null ? 0 : getLeft().hashCode();
int hRight = getRight() == null ? 0 : getRight().hashCode();
return hLeft + (37 * hRight);
} // end method
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('<');
if( left == null ) {
sb.append("null");
} else {
sb.append(left.toString());
} // end if
sb.append(',');
if( right == null ) {
sb.append("null");
} else {
sb.append(right.toString());
} // end if
sb.append('>');
return sb.toString();
} // end method
} // end class
I just ran into this problem myself, and in my -particular- case, I didn't need to know the type E.
For example:
public class Example<E> {
E value;
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Example<?> other = (Example<?>) obj;
if (value == null) {
if (other.value != null)
return false;
} else if (!value.equals(other.value))
return false;
return true;
}
}
In the above code, there is no unchecked cast because of using Example<?>
. The type parameter wildcard '?' saves the day.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With