为什么与模板类无关的集合会丢弃其类型?这是一个示例:(很抱歉,由于我感到困惑,因此无法编译。)
package test; import java.util.ArrayList; import java.util.List; public class TemplateTest { public static class A { } public static class B<T extends Comparable> { List<A> aList = new ArrayList<A>(); public List<A> getAList() { return aList; } public int compare(T t, T t1) { return t.compareTo(t1); } } public static void main(String[] args) { B b = new B(); for (A a : b.getAList()) { //THIS DOES NOT WORK } List<A> aList = b.getAList(); //THIS WORKS for (A a : aList) { } } }
此代码在编译时引发错误:
test/TemplateTest.java:24: incompatible types found : java.lang.Object required: test.TemplateTest.A for (A a : b.getAList()) {
如果我指定了Blike 的模板B,或者如果我从B完全删除了模板,那么一切正常。
这是怎么回事?
编辑:人们指出没有必要使B通用,所以我添加到B
是的,众所周知的行为是,如果您使用原始类型,则该类上的所有类型参数都会丢失,而不仅仅是您未能声明的类型级别参数。
问题部分在这里:
如果我将B的模板指定为like B<String>,或者如果我从B完全删除了模板,那么一切正常。
B<String>
这不是一个选择,您不必选择是否要指定type参数。它不指定任何参数就进行编译的唯一原因是为了向后兼容。缺少类型参数的情况下编写新代码是编程错误。
List<A> list =b.getList()不能成功地解释类型,它只是有效地坚持了任意强制转换,并让您相信分配是正确的。如果您查看编译器警告,则实际上是在为不安全的转换生成警告。
List<A> list =b.getList()
for(A a : b.getList()) {} 将该警告升级为错误,因为插入的强制转换将在编译器生成的代码内部,因此它完全拒绝自动生成不安全的代码,而不仅仅是发出警告。
for(A a : b.getList()) {}
根据Java语言规范:
仅允许使用原始类型作为对遗留代码兼容性的让步。强烈建议不要在将通用性引入Java编程语言后在代码中使用原始类型。Java编程语言的未来版本可能会禁止使用原始类型。
最重要的是,Java泛型与C ++模板唯一共享的重要内容是<>语法:)
更多详细信息:什么是原始类型,为什么我们不应该使用它?