为什么赢了';这个通用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("");