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

查看:117
本文介绍了为什么不能编译这个通用的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?
    }
}

我得到这个编译器错误。

I get this compiler error.

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节(原始类型)

From section 4.8 (raw types) of the JLS:


构造函数的类型(§8.8),
实例方法(§8.8,§9.4)或
非静态字段(§8.3)未从其
超类或超接口继承的原始
类型C是在对应于C的通用
声明中删除其类型的

类型的a原始类型
的静态成员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.

因此,即使方法的类型签名没有使用类本身的任何类型参数,输入erasure并且签名变得有效

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).

编辑:此代码:

This code:

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

编译是因为原始的 Map 存在隐式但未经检查的转换c $ c>键入映射< String,String> 。您可以通过在最后一种情况下进行显式转换(在执行时不做任何事情)来获得相同的效果:

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天全站免登陆