2

为什么编译器不产生任何错误?我可以在 JLS 的什么地方了解到这种情况?

class Main {
  public static void main(String[] args) {
    A a = new A();

    List<Integer> list = a.getStrings();
  }

  static class A<X> {
    public List<String> getStrings() {
      return new ArrayList<String>();
    }
  }
}
4

2 回答 2

5

您可以在JLS §4.8中了解这种情况:

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

为了确保始终标记可能违反类型规则的行为,对原始类型成员的某些访问将导致编译时未经检查的警告。访问原始类型的成员或构造函数时编译时未检查警告的规则如下:

  • 在对字段进行赋值时:如果左侧操作数的类型是原始类型,则如果擦除更改了字段的类型,则会出现编译时未经检查的警告。

  • 在调用方法或构造函数时:如果要搜索的类或接口的类型(第 15.12.1 节)是原始类型,则如果擦除更改了方法的任何形式参数类型,则会出现编译时未经检查的警告或构造函数。

  • 当形式参数类型在擦除下没有改变(即使结果类型和/或 throws 子句改变)时,对于从字段读取,或者对于创建原始的类实例,不会发生编译时未经检查的警告类型。

于 2013-08-21T15:02:09.103 回答
2

这就是所谓的使用原始类型。这是由于遗留原因而在语言中使用的,因为泛型并不总是 Java 的一部分。

而且由于您无论如何都不使用泛型类型参数,因此它只会被删除。正如评论者指出的那样,如果您在类型擦除后没有指定类型参数,它将是一个Object.

于 2013-08-21T14:59:45.950 回答