[英]Java: using typed variables in a generic class
有人可以向我解释为什么这段代码不能编译?
即使它使用泛型类而不提供特定类型T,它应该能够在编译时识别ArrayList保存字符串。
public class Test {
public static void main(String[] args){
Container container = new Container();
container.strings.add("test");
String s1 = container.strings.get(0); // does not compile
ArrayList<String> local = container.strings;
String s2 = local.get(0); // does compile
}
static class Container <T>{
ArrayList<String> strings = new ArrayList<String>();
}
}
当您使用泛型类作为原始类型(未指定类型的类型)时, 将从类中剥离所有通用信息 (是否使用省略的类型)。
因此,当您对Container container
(而不是Container<SomeClass> container
)进行编码时, ArrayList<String> strings
将成为ArrayList strings
,其使用方式就像它是ArrayList<Object>
。
要“修复”,请指定Container
的类型(即使您不使用该类型):
Container<Object> container = new Container<Object>();
其余的将现在编译。
这样做的原因是向后兼容早期的Java前通用版本(1.4及更早版本)
正如波西米亚人所说,原始类型中的每个类型参数都被抛弃了。 一开始我觉得这是一个bug,但是在bug数据库(#6244346)中甚至还有一个条目明确引用了相关的JLS§4.8
未从其超类或超接口继承的原始类型C的构造函数(第8.8节),实例方法(第8.4节,第9.4节)或非静态字段(第8.3节)M的类型是对应的原始类型在对应于C的通用声明中擦除其类型
原始类型C的静态方法或静态字段的类型与其对应于C的泛型声明中的类型相同。
将类型参数传递给未从其超类或超接口继承的原始类型的非静态类型成员是一个编译时错误。
尝试将参数化类型的类型成员用作原始类型是编译时错误。
您无法从原始List
获取String
的原因,但是您可以将List
分配给List<String>
,因为在后者中编译器会发出警告( 未经检查的转换 ),但您不报告它(执行你看了警告,不是吗?:P)。 我用javac和Eclipse编译器测试了你的代码,并且都遵守规范。
引入了原始类型以便与遗留代码进行互操作,但在这种情况下,我无法弄清楚如何保留非静态成员的类型信息会破坏事物。 使用参数化类型而不是原始类型意味着代码部分移植 ,因此在这种情况下,目的可能不仅仅是反向计算,而是确保连贯的代码库,代码是完整的1.4,或者它完全是Java 5+。 另一个选择是使用这样的原始类型可能会减慢类似上下文中无界通配符的采用速度。
BTW(但我认为你自己想通了)如果你不使用type参数,你可以简单地使用一个无界的通配符,即Container<?>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.