带有列表的原始类型< String>给编译错误 [英] Raw Type with List<String> gives compilation error

查看:181
本文介绍了带有列表的原始类型< String>给编译错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下通用类:

  import java.util.ArrayList; 
import java.util.List;

公共类GenericRaw< T> {
public List< String> get(){
返回新的ArrayList<>();
}
}

让我们考虑一下它的用法: p>

  public class用法{
public void doSomething(){
GenericRaw base = new GenericRaw();
for(String x:base.get()){}
}
}

对于这段代码,Idea并没有给出任何编译错误,但是Java编译器本身并没有这样做:


java:不兼容类型
required:java.lang.String
found:java.lang.Object

可在JDK上重现1.6.0_33以及JDK 1.7.0_17。



有人可以帮我解释这个问题吗?



我的调查结果。
以下变体可以成功编译:


  public void doSomething(){
GenericRaw<> base = new GenericRaw();
for(String x:base.get()){}
}


甚至:


  public void doSomething(){
GenericRaw base = new GenericRaw();
列表< String> list = base.get();
for(String x:list){}
}




$

当然。它遵循JLS对原始类型的描述,在 4.8节


为了便于与非通用遗留代码进行交互,可以使用擦除类型(§4.6)的参数化类型(§4.5)或删除数组类型(§10.1)的元素类型是参数化类型。这种类型被称为原始类型。


GenericRaw< T> 的specs / jls / se7 / html / jls-4.html#jls-4.6rel =nofollow>擦除为:

  public class GenericRaw {
public List get(){...}
}
$ b


类型擦除还将构造函数或方法的签名(第8.4.2节)映射到没有参数化类型或类型变量的签名。删除构造函数或方法签名s是一个签名,它包含与s相同的名称和s中给出的所有形式参数类型的删除。

类型参数(§8.4.4)和方法的返回类型(§8.4.5),如果构造函数或方法的签名被擦除,它也会被擦除。



I have the following Generic class:

import java.util.ArrayList;
import java.util.List;

public class GenericRaw<T> {
    public List<String> get() {
         return new ArrayList<>();
    }
}

Let us consider the case of its usage:

public class Usage {
    public void doSomething() {
        GenericRaw base = new GenericRaw();
        for (String x : base.get()) {   }
    }
}

For this code Idea doesn't give any compilation error but Java compiler itself does:

java: incompatible types required: java.lang.String found: java.lang.Object

Reproducible on JDK 1.6.0_33 as well as on JDK 1.7.0_17.

Can someone help me with the explanation of this issue?

Results of my investigations. The following variants can be successfully compiled:

public void doSomething() {
    GenericRaw<?> base = new GenericRaw();
    for (String x : base.get()) {   }
}

or even:

public void doSomething() {
    GenericRaw base = new GenericRaw();
    List<String> list = base.get();
    for (String x : list) {   }
}

解决方案

Can someone help me with the explanation of this issue?

Sure. It's following the JLS's description of raw types, in section 4.8:

To facilitate interfacing with non-generic legacy code, it is possible to use as a type the erasure (§4.6) of a parameterized type (§4.5) or the erasure of an array type (§10.1) whose element type is a parameterized type. Such a type is called a raw type.

The erasure of GenericRaw<T> is:

public class GenericRaw {
    public List get() { ... }
}

because:

Type erasure also maps the signature (§8.4.2) of a constructor or method to a signature that has no parameterized types or type variables. The erasure of a constructor or method signature s is a signature consisting of the same name as s and the erasures of all the formal parameter types given in s.

The type parameters of a constructor or method (§8.4.4), and the return type (§8.4.5) of a method, also undergo erasure if the constructor or method's signature is erased.

这篇关于带有列表的原始类型&lt; String&gt;给编译错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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