I\'m trying to override equals
method for a parameterized class.
@Override
public boolean equals(Object obj) {
if (this == obj)
return t
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.
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>
?
Use reflection. http://tutorials.jenkov.com/java-reflection/generics.html
Off-topic - do you realise that according to your implementation, Tuple(a0, a1) is equal to Tuple(a1, a1)? I suspect that's not what you want...
On-topic, as others have said, erasure makes this impossible. But you should reconsider why you want this - equality checking only happens at runtime, and generics are only compile-time. Conceptually, a variable has generic parameters, but an object does not. Thus when you're comparing the equality of objects, the generic parameters do not matter at all; you can't take any appropriate action based on them at runtime anyway.
Object equality, and generic parameter co-/contra-variance, are two orthogonal concerns.
I agree with the comments above, why does the class E need to be equal? and how do you want to treat subclasses of E?
Anyway, given that here is a code sample that may help you:
public class Example<T> {
T t;
public Example(T t) {
this.t = t;
}
public static void main(String[] args) {
final String s = "string";
final Integer i = 1;
final Number n = 1;
final Example<String> exampleString = new Example<String>(s);
final Example<Integer> exampleInteger = new Example<Integer>(i);
final Example<Number> exampleNumber = new Example<Number>(n);
System.out.println("exampleString subclass " + exampleString.t.getClass());
System.out.println("exmapleIntger subclass " + exampleInteger.t.getClass());
System.out.println("exmapleNumber subclass " + exampleNumber.t.getClass());
System.out.println("Integer equals Number = " +
exampleInteger.t.equals(exampleNumber.t));
}
}
You can call t.getClass() to get class information about the type of T (assuming it is not null, of course.)
I hope this helps.
Sadly, you can't do this at compile time; the information is gone. Such are the consequences of type erasure. An alternative is to store the parameter as a Class
instance, and then look it up later.