Java 使用泛型破坏类型安全

Java 使用泛型破坏类型安全,java,generics,type-safety,type-theory,Java,Generics,Type Safety,Type Theory,当我能够破坏类型安全时,我有以下代码 private静态数组列表cast2(){ //这一行编译(1) 返回(ArrayList)新的ArrayList(); } 私有静态ArrayList cast3(){ //不编译(3) 返回(ArrayList)新的ArrayList(); } 公共静态void main(字符串[]argv){ ArrayList ld1=cast2(); //这不是(2) ArrayList ld2=(ArrayList)新建ArrayList(); } 很明显,第

当我能够破坏类型安全时,我有以下代码

private静态数组列表cast2(){
//这一行编译(1)
返回(ArrayList)新的ArrayList();
}
私有静态ArrayList cast3(){
//不编译(3)
返回(ArrayList)新的ArrayList();
}
公共静态void main(字符串[]argv){
ArrayList ld1=cast2();
//这不是(2)
ArrayList ld2=(ArrayList)新建ArrayList();
}
很明显,第(2)行和第(3)行不是类型安全的,并且不编译。我被编译的第(1)行搞糊涂了。在函数cast2中用Double代替T之后,与cast3相同,但cast2编译,而cast3不编译

如果ArrayList的子类型只有ArrayList本身,为什么可以从ArrayList强制转换为未知类型ArrayList

在函数cast2中用T代替Double之后,cast3与cast2相同,但cast2编译,而cast3不编译

因为Java泛型的工作方式不是“用
t
代替
Double
”,而是使用擦除。泛型只是编译时的一种东西。
cast2()
的实际实现是

return new ArrayList();
…完全没有
。一旦编译了
cast2()
,您就可以用任何东西调用它,它不会在意

在函数cast2中用T代替Double之后,cast3与cast2相同,但cast2编译,而cast3不编译

因为Java泛型的工作方式不是“用
t
代替
Double
”,而是使用擦除。泛型只是编译时的一种东西。
cast2()
的实际实现是

return new ArrayList();


…完全没有
。一旦编译了
cast2()
,您就可以用任何东西调用它,它不会在意。

它会发出警告。如果执行未选中的强制转换,则可以破坏类型安全性;这就是警告告诉您的。@LouisWasserman我可以看到警告,但即使编译器发出警告,它也允许我编译第1行,而不允许我编译第2行。是的。为什么这么奇怪?第1行没有查看
cast2()的实现内部。一旦编译了
cast2()
,编译器就相信它能做到它所说的一切。@LouisWasserman我在问题正文中解释了我的推理。这看起来很奇怪,因为在进行类型替换之后,这两行基本上是相同的,除了一个额外的函数调用。您刚刚发现了它:中间有一个调用,方法中有一个泛型类型参数。我猜编译器相信我们没有那么邪恶:)它提出了一个警告。如果执行未选中的强制转换,则可以破坏类型安全性;这就是警告告诉您的。@LouisWasserman我可以看到警告,但即使编译器发出警告,它也允许我编译第1行,而不允许我编译第2行。是的。为什么这么奇怪?第1行没有查看
cast2()的实现内部。一旦编译了
cast2()
,编译器就相信它能做到它所说的一切。@LouisWasserman我在问题正文中解释了我的推理。这看起来很奇怪,因为在进行类型替换之后,这两行基本上是相同的,除了一个额外的函数调用。您刚刚发现了它:中间有一个调用,方法中有一个泛型类型参数。我猜编译器相信我们没有那么邪恶:)那么为什么它甚至允许我将ArrayList转换为ArrayList呢。它应该知道ArrayList的唯一子类型是ArrayList,所以转换泛型是没有意义的。因为当您执行导致警告的转换时,编译器相信您比它知道得更好。在本例中,它会起作用--将
new ArrayList()
强制转换为
ArrayList()
将生成一个
ArrayList
,效果很好。它只起作用是因为我没有向列表中添加任何内容。如果我在那里添加了一些整数,那么我可以将其转换为双精度,这是非法的。@Trismegistos:是的,它可以工作,因为在进行转换时它是空的,并且没有保留对它的引用。Java不会试图解决这些细节。如果你告诉它你正在强制转换到一个通用参数,而你忽略了说它不安全的警告,那么它会假设你知道你在做什么。那么为什么它甚至允许我将ArrayList强制转换为ArrayList呢。它应该知道ArrayList的唯一子类型是ArrayList,所以转换泛型是没有意义的。因为当您执行导致警告的转换时,编译器相信您比它知道得更好。在本例中,它会起作用--将
new ArrayList()
强制转换为
ArrayList()
将生成一个
ArrayList
,效果很好。它只起作用是因为我没有向列表中添加任何内容。如果我在那里添加了一些整数,那么我可以将其转换为双精度,这是非法的。@Trismegistos:是的,它可以工作,因为在进行转换时它是空的,并且没有保留对它的引用。Java不会试图解决这些细节。如果你告诉它你正在使用一个通用的参数,而你忽略了说它不安全的警告,那么它假设你知道你在做什么。