为什么一个地方的原始类型会导致其他地方的通用调用被视为原始?

soc*_*soc 12 java generics overloading language-design raw-types

考虑这个例子:

import java.util.*;

class Foo<T> {
  public int baz(List<String> stringlist) { return 1; }
  public int baz(ArrayList<Object> objectlist) { return 2; }

  public static void main(String[] args) {
    Foo<String> foo = new Foo<String>(); // (A)
    //Foo foo = new Foo();               // (B)

    System.out.println(foo.baz(new ArrayList<String>()));
  }
}
Run Code Online (Sandbox Code Playgroud)

为什么它打印1(A),而是2(B)

我知道方法解析是如何工作的,所以不需要向我解释.

我想知道这个"特征"背后的深层动机.为什么没有关于它的擦除警告?(只有一个Foo foo = new Foo().)

尽管给出了泛型类型,为什么方法解析使用擦除语义?

fin*_*nnw 5

这是因为当编译器解析重载时,它会将每个方法视为泛型或非泛型,而不是两者的混合,因此候选者是:

  1. Foo<T>.baz(List<String>)
  2. Foo<T>.baz(ArrayList<Object>)

如果fooFoo<String>,或

  1. Foo.baz(List)
  2. Foo.baz(ArrayList)

如果fooFoo.

没有这样的事情Foo.baz(List<String>).要么考虑所有类型参数,要么都不考虑.(我不知道在JLS中明确说明了这一点,但它有意义,因为将泛型方法视为原始等效方法是向后兼容性功能.)

在第一种情况下,Foo<T>.baz(List<String>)匹配,但Foo<T>.baz(ArrayList<Object>)没有.

在第二种情况下两者的功能相匹配,并且Foo.baz(ArrayList)更具体的,所以它被选中.