我想重写泛型类中的equals()方法,并且必须将Object强制转换为我的泛型类型Pair。
我添加了@SuppressWarnings(“ unchecked”)来“静音”警告,但是问题仍然存在。方法getType()和getClass()也不适用于泛型类型,因此使用T.getType()成为不可能。
public class Pair<T, U> {
private T first;
private U second;
public Pair(T _first, U _second)
{
first = _first;
second = _second;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
//Problem ahead!!!
Pair<T, U> other = (Pair<T, U>) obj;
...
}
}
是否有一般的良好做法或“技巧”来正确,安全地执行此操作?
答案 0 :(得分:5)
您可以将obj
投射到Pair<?, ?>
上,并在equals
和first
上调用second
:
Pair<?, ?> other = (Pair<?, ?>) obj;
return other.first.equals(first) && other.first.equals(second);
通过这种方式,T.equals
和U.equals
的类型检查将由T
和U
处理。
答案 1 :(得分:3)
您可以这样编写equals
方法:
@Override
public boolean equals(Object object) {
boolean equal = false;
if(this == object){
equal = true;
} else if(object instanceof Pair<?, ?>) {
// Check that object is an instance of Pair<?, ?>, this will also null check.
// Then just case object to Pair<?, ?> like.
Pair<?, ?> pair = (Pair<?, ?>) object;
if(((this.first == null && pair.first == null) || (this.first != null && this.first.equals(pair.first))) &&
((this.second == null && pair.second == null) || (this.second != null && this.second.equals(pair.second)))){
equal = true;
}
}
return equal;
?
之间的<>
有点像通配符,实际上被归类为无界通配符;这意味着尚未指定类的类型。
object instanceof Pair<?, ?>
将检查两件事,首先将检查对象是否不为空,因此为您创建null
的安全性,然后它将检查对象的类型为{{1} }。
您可以了解通配符here
根据Pair<?, ?>
,如果您要覆盖ntalbs
,请不要忘记也覆盖equals
。
hashCode
为什么覆盖@Override
public int hashCode() {
final int prime = 31;
int result = super.hashcode;
result = result * prime + (this.first == null ? 0 : this.first.hashCode());
result = result * prime + (this.second == null ? 0 : this.second.hashCode());
return result;
}
时必须覆盖hashCode
?
您必须在每个覆盖equals()的类中重写hashCode()。否则,将违反Object.hashCode()的一般约定,这将阻止您的类与所有基于哈希的集合(包括HashMap,HashSet和Hashtable)一起正常运行。
答案 2 :(得分:2)
您可以使用instanceof
检查对象的类型,然后安全地对其进行投射。
if(obj instanceof Pair){
Pair other = (Pair) obj;
}
答案 3 :(得分:1)
首先要记住,泛型仅在编译时处于活动状态。它们是编译时检查的额外一层,以确保您不会误用可能采用不同类型的容器或函数。
还请记住,equals()
自Java的第一个发行版以来就一直存在,而泛型是在Java 1.5中引入的。因此,对于这种特定的方法,您自然会进行某种类型转换。
在投射对象之后,无论如何,您都将检查Pair
的每个单独的元素,因此,如果它们的类型不同,它们也将通过相等性检查。
答案 4 :(得分:1)
由于泛型类型在编译时被擦除,因此您无法在运行时检查该类型。因此,您应该将其强制转换为equals
。
如果使用JDK 7或更高版本,则还可以在Pair<?,?>
方法中使用Objects.equals(..)
。这将简化代码,因为您不必担心equals
或first
是second
。
null
此外,如果您在类中添加了Pair<?, ?> pair = (Pair<?, ?>) obj;
return Objects.equals(first, pair.first) &&
Objects.equals(second, pair.second);
方法,请不要忘记实现hashCode
。
equals
答案 5 :(得分:-1)
package com.journaldev.generics;
public class GenericsMethods {
//Java Generic Method
public static <T> boolean isEqual(GenericsType<T> g1, GenericsType<T> g2){
return g1.get().equals(g2.get());
}
public static void main(String args[]){
GenericsType<String> g1 = new GenericsType<>();
g1.set("Test");
GenericsType<String> g2 = new GenericsType<>();
g2.set("Test");
boolean isEqual = GenericsMethods.<String>isEqual(g1, g2);
//above statement can be written simply as
isEqual = GenericsMethods.isEqual(g1, g2);
//This feature, known as type inference, allows you to invoke a generic method as an ordinary method, without specifying a type between angle brackets.
//Compiler will infer the type that is needed
}
}