I\'m trying to override equals
method for a parameterized class.
@Override
public boolean equals(Object obj) {
if (this == obj)
return t
The suggestions to retain a reference to E
's type with a Class
object seem inefficient (that's a lot of pointless references to a Class
taking up memory) and pointless for your problem.
It's not generally true that Foo<Bar>
andFoo<Baz>
should be unequal. So you don't need E
. And, in the code you wrote, you don't even need it to compile. Simply cast to Tuple<?>
, since that is truly all you know about Tuple
at that point. It still compiles and all.
If you are passed Tuple
s with data of two wildly different types, those elements will not be equals
, and your method will return false
, as desired. (One hopes -- depends on those types implementing equals
sanely.)
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
Since generics are erased at compile time, you basically can't. At runtime, any type parameter is gone, and as far as the JVM is concerned, they are exactly the same in all respects.
The way to work around that is to store a Class
field that represents the type, and create the object with that type in the constructor.
A sample constructor:
public class Tuple < E > {
public Tuple(Class<E> c) {
//store the class
}
}
Or you could use a factory:
public static <E> Tuple <E> getTuple(Class<E> type) {
// Create and return the tuple,
// just store that type variable in it
// for future use in equals.
}