簡體   English   中英

java和equals()方法中的泛型類:類型安全

[英]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<?, ?>並在firstsecond上調用equals

Pair<?, ?> other = (Pair<?, ?>) obj;
return other.first.equals(first) && other.first.equals(second);

這樣,類型檢查將由T.equalsU.equals處理,無論TU是什么。

你可以寫這樣的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(..) 這將簡化代碼,因為如果firstsecondnull則無需擔心。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM