为什么赢了';这个通用java代码不能编译吗?
在这个简化的示例中,我有一个泛型类和一个返回映射的方法,而不管类型参数是什么。当我没有在包含类上指定类型时,为什么编译器会清除映射上的类型为什么赢了';这个通用java代码不能编译吗?,java,generics,Java,Generics,在这个简化的示例中,我有一个泛型类和一个返回映射的方法,而不管类型参数是什么。当我没有在包含类上指定类型时,为什么编译器会清除映射上的类型 import java.util.Map; public class MyClass<T> { public Map<String, String> getMap() { return null; } public void test() { My
import java.util.Map;
public class MyClass<T>
{
public Map<String, String> getMap()
{
return null;
}
public void test()
{
MyClass<Object> success = new MyClass<Object>();
String s = success.getMap().get("");
MyClass unchecked = new MyClass();
Map<String, String> map = unchecked.getMap(); // Unchecked warning, why?
String s2 = map.get("");
MyClass fail = new MyClass();
String s3 = fail.getMap().get(""); // Compiler error, why?
}
}
嗯。。。不幸的是,我不能告诉你为什么失败。但我可以给你一个简单的解决方法: 将
fail
的类型更改为MyClass
,那么它就可以正常编译了。明白了。这实际上并不是一个bug,看起来很奇怪
发件人:
建造师的类型(§8.8),
实例方法(§8.8,§9.4),或
非静态场(§8.3)M的原始场
不是从其
超类或超接口是
在泛型中删除其类型
与C.相对应的声明
原始类型的静态成员的类型
C与中的类型相同
对应于
C
因此,即使方法的类型签名不使用类本身的任何类型参数,类型擦除也会起作用,签名变得有效
public Map getMap()
换句话说,我认为您可以将原始类型想象为与泛型类型相同的API,但所有
位都从任何地方移除(在API中,而不是在实现中)
编辑:此代码:
MyClass unchecked = new MyClass();
Map<String, String> map = unchecked.getMap(); // Unchecked warning, why?
String s2 = map.get("");
泛型类型在编译后被删除 当您这样做时:
Map<String, String> map = unchecked.getMap();
因为map是map类型
然而,当你
String s3 = fail.getMap().get("");
您没有将fail.getMap()强制转换为任何对象,因此它被认为是简单的Map,而不是Map
在后者中,您应该做的是:
String s3 = ((Map<String, String>fail.getMap()).get("");
strings3=((Mapfail.getMap()).get(“”);
这仍然会发出警告,但无论如何都会起作用。非常有趣的问题,Jon Skeet的回答非常有趣 我只想补充一点关于java编译器这种行为的愚蠢与否 我认为编译器假定如果不在generc类中指定类型参数,则根本无法(或不希望)使用任何类型参数。您可以使用早于5的java版本,或者喜欢手动进行强制转换
这对我来说似乎并不愚蠢。强制转换也很好。为什么类型?会影响地图的类型?对我来说仍然没有意义。@Motlin:Jon解释得很好:MyClass不是原始类型。现在我明白了为什么你的解决方法有效,我将使用它而不是强制转换。谢谢。未经检查的类的确切文本是什么警告?警告:[未检查]未检查的转换为什么第一个编译?“擦除”不是完整的答案。嗯…这有点道理…但同时它也非常愚蠢。。。
String s2 = map.get("");
String s3 = fail.getMap().get("");
String s3 = ((Map<String, String>fail.getMap()).get("");