无法理解 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>
而言,在运行时不存在类(Class)有关。 name
只是一个 Object
具有 Date
的引用里面。但是,任何时候您编写的代码都会消耗 name
在某种程度上,运行时环境需要知道它是特定类型(在本例中为 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
是,它基本上转换p.name
作为Object
打电话前getClass()
在上面。
换句话说,这是您实际编译的代码:
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());
}
关于java - 泛型方法和泛型类中的类型推断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26314668/