How to implement equal for generic types?
Suppose I have a generic container type like:
public final class Container<T> {
public final T t;
public Container(final T t) {
this.t = t;
}
}
I want to implement equals to get this through:
final Container<Object> a = new Container<>("Hello");
final Container<String> b = new Container<>("Hello");
assertNotEquals(a, b);
Instances of a
and b
must be different because their type parameter is T
different.
However, due to erasure, this is difficult to do. This implementation, for example, is wrong:
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj != null && obj instanceof Container<?>) {
final Container<?> other = (Container<?>)obj;
return Objects.equals(this.t, other.t);
}
return false;
}
I expect that I will need to store some kind of token for T
.
How to implement equal for generic types?
This doesn't answer the question.
source to share
you can modify the Container class a bit and add this field:
public final Class<T> ct;
with this and the equation of equality, then
System.out.println(a.equals(b));
will return false
because the equals method checks Class<String>
vsClass<Object>
class Container<T> {
public final T t;
public final Class<T> ct;
public Container(final T t, Class<T> ct) {
this.t = t;
this.ct = ct;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = (prime * result) + ((ct == null) ? 0 : ct.hashCode());
result = (prime * result) + ((t == null) ? 0 : t.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Container other = (Container) obj;
if (ct == null) {
if (other.ct != null)
return false;
} else if (!ct.equals(other.ct))
return false;
if (t == null) {
if (other.t != null)
return false;
} else if (!t.equals(other.t))
return false;
return true;
}
}
source to share