[英]Java generics: is-A relation to Object
我試圖了解泛型類及其具體實例的功能,以及泛型集合的功能。
假設我定義了一個通用類: Stack<T>
現在我正試圖以這種方式使用它:
Stack<String> ts = new Stack<>(5);
Stack<Object> to = new Stack<>(5);
to = ts // compilation error!
所以很明顯Stack<String>
不是Stack<Object>
。
當我定義通用集合時,我感到困惑:
Set<E> elemnts = new Hashset<>();
並注意到我可以使用elements.toString()
! 這意味着Set<E> elemnts
擴展了Object
! 那么這里到底發生了什么?
編譯錯誤並不表示String
不是Object
,這不是真的。 例如,以下代碼可以正常工作:
String s = "I am String!";
Object o = s;
錯誤的意思是Stack<String>
不是Stack<Object>
。 例如,您可以在Stack<Object>
上調用push(new Object())
,但顯然不能在Stack<String>
上調用。
對於以下內容:
Stack<String> ts = new Stack<>(5);
Stack<Object> to = new Stack<>(5);
to = ts // compilation error!
是的,此編譯失敗,因為泛型本質上是強制類型安全的編譯器的功能。 就虛擬機而言,它們實際上只是一個Stack類。
這個說法:
Set<E> elemnts = new Hashset<>();
等效於:
Set<E> elemnts = new Hashset<E>();
該表示法是在Java 7中引入的,由於<>
的緣故有時被稱為“鑽石運算符”。 只是為了消除冗余。
就像擴展Java中的所有類一樣,它是擴展對象的Set類。
以下內容適用於代碼中的Class對象:
boolean b = ts.getClass() == to.getClass(); // b is true
字符串類是Object的隱式子類。 由於Object類是java中所有類的超類。 因此,以下聲明有效
String x="hello";
Object o= x;
但是Stack<String>
不是Stack<Object>
的子類。 因此,代碼會給出編譯時錯誤。
Stack<String> ts = new Stack<>(5);
Stack<Object> to = new Stack<>(5);
to = ts // compilation error!
那么Java中的泛型到底是什么? 如dave所述,泛型類型是編譯器強制實施。 確切地說,在運行時,通用類型不再存在。 它們由Object
或通用類型的上限代替。 此過程稱為“ 類型擦除” 。 因此,泛型類型僅在編譯時存在。
那么為什么我們不能將ArrayList<String>
轉換為ArrayList<Object>
呢? 即使類型參數處於關系中( String
是一個Object
),泛型類也不是。 讓我舉一個簡單的例子。 如果
ArrayList<String> strings = new ArrayList<String>();
ArrayList<Object> objects = strings;
如果有一個電話
objects.add(new Object());
應該怎么辦? 由於strings
只能包含String
,因此Java無法將Object
“放入”此列表。 但是另一方面,如果您查看objects
的聲明,則沒有任何暗示,這應該行不通。 因此,即使泛型類型處於關系中,Java也不允許在泛型類之間進行轉換。
但是泛型類型在運行時不存在。 那是什么忙呢? ArrayList<String>
是否在運行時不是真正的ArrayList<Object>
,因此,所有這些都不重要嗎? 好吧 由於您在編譯時知道類型,因此可以使用某些協定。 例如,當從ArrayList<String>
檢索一個元素時,可以確保該檢索到的對象具有public char charAt(int)
方法(因為String
具有此方法)。 如果由於某種原因,此ArrayList<String>
返回一個Object
而不是String
,則無法調用charAt(int)
方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.