在这个简化的例子中,我有一个泛型类,以及一个返回Map而不管类型参数的方法.当我没有在包含类上指定类型时,为什么编译器会清除地图上的类型?
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?
}
}
Run Code Online (Sandbox Code Playgroud)
我得到这个编译错误.
MyClass.java:20: incompatible types
found : java.lang.Object
required: java.lang.String
String s3 = fail.getMap().get(""); // Compiler error
Run Code Online (Sandbox Code Playgroud)
Jon*_*eet 35
得到它了.这实际上不是一个错误,看起来很奇怪.
未从其超类或超接口继承的原始类型C的构造函数(第8.8节),实例方法(第8.8节,第9.4节)或非静态字段(第8.3节)M的类型是其类型的擦除在对应于C的泛型声明中.原始类型C的静态成员的类型与对应于C的泛型声明中的类型相同.
因此,即使方法的类型签名不使用类本身的任何类型参数,类型擦除也会启动并且签名变得有效
public Map getMap()
Run Code Online (Sandbox Code Playgroud)
换句话说,我想你能想象一个原始类型为相同的API泛型类型,但所有<X>
的移除位随处可见(在API中,未实现).
编辑:此代码:
MyClass unchecked = new MyClass();
Map<String, String> map = unchecked.getMap(); // Unchecked warning, why?
String s2 = map.get("");
Run Code Online (Sandbox Code Playgroud)
编译,因为从原始Map
类型到隐式但未经检查的转换Map<String, String>
.通过在最后一种情况下进行显式转换(在执行时无效),您可以获得相同的效果:
// Compiles, but with an unchecked warning
String x = ((Map<String, String>)fail.getMap()).get("");
Run Code Online (Sandbox Code Playgroud)