簡體   English   中英

Java:檢查泛型是否為 int

[英]Java: Check if a generic is an int

public class Hashing<Key, Elem>

我想檢查 Key 是否是 int,所以我將這些行放在構造函數中:

Key key = null;
if (!(key instanceof Integer)) {
    throw new TypeOfKeyStillNotSupportedException();
}

但是,我以這種方式創建了一個:

tHash = new Hashing<Integer, Movie>(max);

並且該死的 TypeOfKeyStillNotSupportedException() 彈出。 為什么會發生這種情況,我該如何正確地做到這一點?

提前致謝。

編輯:已經發現問題在於分配了 null 的密鑰。 現在的問題是:如何進行檢查?

null不是任何事物的instanceof 由於類型擦除,無法在運行時直接檢查Key的類型。 一種選擇是讓用戶將Class<Key>傳遞給構造函數,以便您可以檢查:

public Hashing(Class<Key> keyType, ...) {
  if (keyType != Integer.class) {
    throw new TypeOfKeyStillNotSupportedException();
  }
  ...
}

...

Hashing<Integer, Foo> hashing = new Hashing<Integer, Foo>(Integer.class, ...);

為了避免重復 arguments 類型,您可以創建 static 工廠方法:

public static <K, E> Hashing<K, E> create(Class<K> keyType, ...) {
  return new Hashing<K, E>(keyType, ...);
}

...

Hashing<Integer, Foo> hashing = Hashing.create(Integer.class, ...);

如果您的代碼有“key = null;” 在 instanceof 測試之前,必然會拋出異常。

原因是 instancof 運算符檢查指向的 object 類型的引用,而不是它的聲明方式。

您可以嘗試使用這個簡單的示例並相應地刪除注釋以查看差異:

public static void main(String[] args) {
    //Object obj = new Integer(9);
    Object obj = null;

    if (!(obj instanceof Integer))
        System.out.println("Not Integer.");
    else
        System.out.println("Is Integer");
}

此外,您可以在此處找到更多詳細信息:

http://download.oracle.com/javase/tutorial/java/nutsandbolts/op2.html

希望能幫助到你:)


Java Generics 的完整示例:

class GenTest<Key extends Integer, Value>{
    Key key;
    Value val;

    GenTest(Key key, Value val){
        this.key = key;
        this.val = val;

        System.out.println("Key: " + key + " Value: " + val);
    }
}

public class GenericRecap {
    public static void main(String[] args) {
        //Object obj = new Integer(9);
        Object obj = null;

        if (!(obj instanceof Integer))
            System.out.println("Not Integer.");
        else
            System.out.println("Is Integer");

        new GenTest<Integer, String>(9, "nine");
    //new GenTest<String, String>("funny", "nine");  // In-Error
    }
}

另請注意,通過使用“Key extends Integer”,如果您傳遞的不是 Integer 的子類,則會在運行時引發異常。 此外,如果您正在使用 IDE 來檢查它,它將被標記為 GenTest Class 的“類型不在范圍內”。

浮點數和 Integer 都繼承自 Number。 因此,您可以“擴展 Number”,然后根據您想在代碼中使用它的方式檢查“instanceof Integer”或“instanceof Float”。

希望它有所幫助:) 干杯!

Java generics 是使用類型擦除實現的:通用信息在用於類型檢查后被編譯器丟棄,因此在運行時您的 class 實際上只是Hashing<Object, Object> 這就是為什么您不能基於泛型類型進行運行時檢查的原因。

您可以向構造函數添加Class<Key>類型的參數,調用者必須為用作鍵的類型傳遞正確的 class object。 例如,在Hashing<Integer, String>中,只有Integer.class將被接受為該參數的值,您可以將其用於運行時類型檢查。 但是,將密鑰的 class object 作為參數傳遞的要求使得構造函數調用看起來有點尷尬。

鑒於您的示例中的以下內容:

public class Hashing<K, E>

這是沒有意義的:因為K是一個Type ,當 class 被專門化時,它可以設置為任何東西。 我將名稱從Key更改為K以消除您可能認為Key不代表Type的混淆。 Type名稱的一般標准是大多數時間使用單個字符。

K key = null;
if (!(key instanceof Integer)) 
{
    throw new TypeOfKeyStillNotSupportedException();
}

如果你把它改成

K key = null;
if (!(key instanceof K)) 
{
    throw new TypeOfKeyStillNotSupportedException();
}

那將是一個更Generic的解決方案,但這也沒有意義,因為key始終K的一種

key不能是null因為null不是任何Type

如果沒有更多關於instanceof檢查的上下文,我不知道您的意圖是什么。

instanceof檢查GenericType是一種代碼味道,無論如何都可能是錯誤的方法。

看這里java.util.HashMap實現如何處理這個問題。

他們只有兩個地方使用instanceof並且都是遺留方法,只接受Object並且不是類型安全的。

處理這種情況的方法是顯式測試 null; 例如

Key key = null;
if (key == null) {
    throw new KeyIsNullException();
} else if (!(key instanceof Integer)) {
    throw new TypeOfKeyStillNotSupportedException();
}

// ... or (for the literal minded) ...

if (key != null && !(key instanceof Integer)) {
    throw new TypeOfKeyStillNotSupportedException();
}

鄭重聲明,那些回應說這與類型擦除有關的人是不靠譜的。 如果Key是明確的 class 或接口,您將獲得完全相同的行為。

(另一方面,如果代碼說someObj instanceof Key ... 由於類型擦除問題,那將是編譯錯誤。)

您需要一個isInstance方法,它是instanceof運算符的動態等效方法。

例如,

Integer.class.isInstance(1); //return true
Integer.class.isInstance(null); //return false

編輯
如果要針對不同的 class 類型進行測試,請編寫如下實用方法:

static <T> boolean isInstance(Class<T> type, Object obj) {
    return type.isInstance(obj);
}

例如,

Hashing.<String>isInstance(String.class, "hi"); // return true

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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