[英]Type inference in generic method & generic class
無法理解Java中的泛型編程。
我讀了一些關於它的教程,但仍然很困惑,特別是當事情變得復雜時。
誰能解釋一下這個例子中發生了什么?
import java.util.Date;
public class Test1 {
public static void main(String[] args) {
P<Cls> p = new P<>(); //<1> //I expect a ClassCastException here, but no. Why? //How does the type inference for class P<E> work?
System.out.println(p.name); //it prints
// System.out.println(p.name.getClass());//but this line throws ClassCastException //why here? why not line <1>?
test1(p);//it runs
// test2(p);//throws ClassCastException//What is going on in method test1&test2?
//How does the type inference for generic methods work in this case?
}
public static<T> void test1(P<? extends T> k){
System.out.println(k.name.getClass());
}
public static<T extends Cls> void test2(P<? extends T> k){
System.out.println(k.name.getClass());
}
}
class P<E>{
E name = (E)new Date();//<2>
}
class Cls{}
P<Cls> p = new P<>();
請記住,Java通過擦除來實現泛型,這意味着P
的構造函數實際上並不知道E
在運行時是什么 。 Java中的泛型純粹是為了在編譯時幫助開發人員。
這意味着當您創建一個new P<>()
,會創建一個new Date()
, 但它實際上並沒有轉換為任何特定類型,因為運行時對E
沒有任何了解 。 E
在運行時不存在,只要P<E>
類而言。 name
只是一個內部有Date
的Object
引用。 但是,每當您編寫以運行時環境需要知道它是特定類型(在本例中為Cls
)的方式使用name
代碼時,編譯器會在不告訴您的情況下將強制轉換插入該類型。
p.name.getClass()
被編譯為((Cls)p.name).getClass()
,它將創建一個類((Cls)p.name).getClass()
異常。 test2()
指定非泛型的類型約束( extends Cls
)。 因此,它對p.name.getClass()
調用同樣被轉換為((Cls)p.name).getClass()
。 另一方面:
System.out.println(p.name)
實際上與System.out.println((Object)p.name)
相同,因為println
是一個采用object
的非泛型方法。 test1(p.name)
類似。 因為運行時實際上並不知道T
是什么類型,所以它在調用getClass()
之前基本上將p.name
強制轉換為Object
。 換句話說,這是你的代碼,因為它實際上被編譯:
class P{
Object name = new Date();
}
public static void main(String[] args) {
P p = new P();
System.out.println(p.name);
System.out.println(((Cls)p.name).getClass());
test1(p);
test2(p);
}
public static void test1(P k){
System.out.println(k.name.getClass());
}
public static void test2(P k){
System.out.println(((Cls)k.name).getClass());
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.