[英]Generic classes in java and equals() method: type safety
我想覆蓋泛型類中的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;
...
}
}
是否有正確和安全的一般良好做法或“技巧”?
您可以將obj
轉換為Pair<?, ?>
並在first
和second
上調用equals
:
Pair<?, ?> other = (Pair<?, ?>) obj;
return other.first.equals(first) && other.first.equals(second);
這樣,類型檢查將由T.equals
和U.equals
處理,無論T
和U
是什么。
你可以寫這樣的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<?, ?>
的object instanceof Pair<?, ?>
將檢查兩件事,首先它將檢查對象是否為null,因此為您創建null
安全性,然后它將檢查該對象是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;
}
當我覆蓋equals
時,為什么必須覆蓋hashCode
?
您必須覆蓋覆蓋equals()的每個類中的hashCode()。 如果不這樣做,將導致違反Object.hashCode()的常規合同,這將阻止您的類與所有基於散列的集合(包括HashMap,HashSet和Hashtable)一起正常運行。
您可以使用instanceof
檢查對象的類型,然后安全地進行轉換。
if(obj instanceof Pair){
Pair other = (Pair) obj;
}
首先要記住,泛型只在編譯時才有效。 它們是額外的編譯時檢查層,以確保您不會濫用可能采用不同類型的容器或函數。
還要記住,自Java第一版發布以來, equals()
一直存在,而Generics則是在Java 1.5中引入的。 因此,對於這種特定方法,您可以進行一些類型轉換。
鑄造對象后,您將被無論如何檢查的每個元素Pair
,所以如果他們是不同類型的,他們會失敗的平等檢查過。
由於泛型類型在編譯時被擦除,因此無法在運行時檢查類型。 所以你應該把它投射到Pair<?,?>
。
如果使用JDK 7或更高版本,則還可以在equals
方法中使用Objects.equals(..)
。 這將簡化代碼,因為如果first
或second
為null
則無需擔心。
Pair<?, ?> pair = (Pair<?, ?>) obj;
return Objects.equals(first, pair.first) &&
Objects.equals(second, pair.second);
另外,如果在類中添加了equals
方法,請不要忘記實現hashCode
。
@Override
public int hashCode() {
return Objects.hash(first, second);
}
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
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.