为什么这个通用的java代码不能编译? [英] Why won't this generic java code compile?

查看:30
本文介绍了为什么这个通用的java代码不能编译?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这个简化的示例中,我有一个泛型类,以及一个无论类型参数如何都返回 Map 的方法.当我没有在包含类上指定类型时,为什么编译器会清除映射上的类型?

In this simplified example I have a generic class, and a method that returns a Map regardless of the type parameter. Why does the compiler wipe out the types on the map when I don't specify a type on the containing class?

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?
    }
}

我收到此编译器错误.

MyClass.java:20: incompatible types
found   : java.lang.Object
required: java.lang.String
                String s3 = fail.getMap().get("");  // Compiler error

推荐答案

明白了.这实际上不是一个错误,看起来很奇怪.

Got it. This actually isn't a bug, strange as it might seem.

来自 JLS 的 第 4.8 节(原始类型):

构造函数的类型(第 8.8 节),实例方法(第 8.8 节,第 9.4 节),或原始数据的非静态字段 (§8.3) M不是从其继承的类型 C超类或超接口是在泛型中擦除其类型对应于 C 的声明.原始类型的静态成员的类型C 与它的类型相同对应的通用声明C.

The type of a constructor (§8.8), instance method (§8.8, §9.4), or non-static field (§8.3) M of a raw type C that is not inherited from its superclasses or superinterfaces is the erasure of its type in the generic declaration corresponding to C. The type of a static member of a raw type C is the same as its type in the generic declaration corresponding to C.

因此,即使该方法的类型签名不使用类本身的任何类型参数,类型擦除也会开始并且签名变得有效

So even though the method's type signature doesn't use any type parameters of the class itself, type erasure kicks in and the signature becomes effectively

public Map getMap()

换句话说,我认为您可以将原始类型想象为与泛型类型相同的 API,但从 到处 中删除了所有 <X> 位(在 API 中,而不是在实现中).

In other words, I think you can imagine a raw type as being the same API as the generic type but with all <X> bits removed from everywhere (in the API, not the implementation).

此代码:

MyClass unchecked = new MyClass();
Map<String, String> map = unchecked.getMap();  // Unchecked warning, why?
String s2 = map.get("");

编译是因为存在从原始 Map 类型到 Map 的隐式但未经检查的转换.您可以通过在最后一种情况下进行显式转换(在执行时什么都不做)来获得相同的效果:

compiles because there's an implicit but unchecked conversion from the raw Map type to Map<String, String>. You can get the same effect by making an explicit conversion (which does nothing at execution time) in the last case:

// Compiles, but with an unchecked warning
String x = ((Map<String, String>)fail.getMap()).get("");

这篇关于为什么这个通用的java代码不能编译?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆