[英]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
檢查Generic
的Type
是一種代碼味道,無論如何都可能是錯誤的方法。
看這里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.