【问题标题】:Odd compiling error with generic classes and lists泛型类和列表的奇怪编译错误
【发布时间】:2014-03-13 22:30:36
【问题描述】:

所以我在使用具有 List(或 Map 或 Set 等)作为属性的泛型类时遇到了一个奇怪的编译错误。

尝试迭代(使用 foreach)列表时发生编译错误:

Sample.java:11: error: incompatible types
        for (String string : s.getStringList()) {
  required: String
  found:    Object

为了清楚起见,我知道这个问题有一个简单的解决方法,但我想了解代码有什么问题

以下是我创建的示例:

import java.util.List;

public class Sample<T> {

    public List<String> stringList;

    public static void main(String[] args) {
        Sample s = new Sample();

        // Why this doesn't work?
        for (String string : s.getStringList()) {

        }

        // Why does both of the following work?
        List<String> newList = s.getStringList();

        Sample<Object> s2 = new Sample<>();
        for (String string : s2.getStringList()) {

        }

    }

    public List<String> getStringList() {
        return stringList;
    }

}

【问题讨论】:

    标签: java generics type-erasure


    【解决方案1】:

    这些行

    Sample s = new Sample();
    
    // Why this doesn't work?
    for (String string : s.getStringList()) {
    
    }
    

    不工作,因为您使用的是Sample 类的原始 形式。当您使用类的原始形式时,类中的所有 泛型,甚至不相关的泛型,都会执行类型擦除。这意味着getStringList 现在只返回Objects 的List,而不是Strings 的List&lt;String&gt;

    Java 的这一部分是在 Java 1.5 中与泛型一起引入的,因此现在使用泛型的旧版本的类将向后兼容。这样,迭代 List(之前必须使用 Object)的东西仍然可以通过使用 List 的原始形式来使用 Object

    JLS, Section 4.8 处理原始类型:

    更准确地说,原始类型被定义为以下之一:

    • 采用泛型类型声明的名称形成的引用类型,没有伴随的类型参数列表。

    未从其超类或超接口继承的原始类型 C 的构造函数(第 8.8 节)、实例方法(第 8.4 节、第 9.4 节)或非静态字段(第 8.3 节)的类型是原始类型对应于 C 对应的泛型声明中删除其类型的类型。

    (强调我的)

    推理:

    仅允许使用原始类型作为对遗留代码兼容性的让步。强烈反对在将泛型引入 Java 编程语言之后编写的代码中使用原始类型。 Java 编程语言的未来版本可能会禁止使用原始类型。

    【讨论】:

    • 写得很好,谢谢!用参考资料和所有内容解释了问题的各个方面。为您 +1,先生
    【解决方案2】:

    您使用的是原始Sample 类型,因此编译器假定您不关心泛型类型,即使对于未在此对象内声明为原始类型的变量也是如此。这是一个奇怪的规则,但它就是这样。如果您关心泛型,则不应使用原始类型。一旦你使用原始类型,它的所有成员也会被编译器视为原始类型。

    【讨论】:

    • @HovercraftFullOfEels:ECJ 也是如此。 非常不直观的行为,老实说......
    猜你喜欢
    • 1970-01-01
    • 2017-08-27
    • 2020-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-22
    • 2016-01-23
    相关资源
    最近更新 更多