【问题标题】:Why do raw types in one place cause generic callsites somewhere else to be treated as raw?为什么一个地方的原始类型会导致其他地方的通用调用点被视为原始类型?
【发布时间】:2011-08-31 07:35:01
【问题描述】:

考虑这个例子:

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>()));
  }
}

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

我知道方法解析的工作原理,所以无需向我解释。

我想知道这个“功能”背后的深层动机。 为什么没有关于它的擦除警告? (只有一个关于Foo foo = new Foo()。)

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

【问题讨论】:

    标签: java generics language-design overloading raw-types


    【解决方案1】:

    这是因为当编译器为resolving overloads时,它会将每个方法视为泛型或非泛型,绝不是两者的混合,所以候选者是:

    1. Foo&lt;T&gt;.baz(List&lt;String&gt;)
    2. Foo&lt;T&gt;.baz(ArrayList&lt;Object&gt;)

    如果fooFoo&lt;String&gt;,或者

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

    如果fooFoo

    没有Foo.baz(List&lt;String&gt;) 这样的东西。要么考虑所有类型参数,要么不考虑。 (我不知道 JLS 中明确说明了这一点,但这是有道理的,因为将泛型方法视为原始等价物是一种向后兼容的特性。)

    在第一种情况下,Foo&lt;T&gt;.baz(List&lt;String&gt;) 匹配但Foo&lt;T&gt;.baz(ArrayList&lt;Object&gt;) 不匹配。

    在第二种情况下,两个函数都匹配,并且Foo.baz(ArrayList)more specific,所以它被选中。

    【讨论】:

      【解决方案2】:

      如果您只保留单个方法baz(ArrayList&lt;Object&gt;),它甚至不会编译案例(A)(错误:方法不能应用于给定类型)。 我猜ArrayList&lt;String&gt; 不是ArrayList&lt;Object&gt; 的子类。

      它在 case (B) 中编译很奇怪,但他们必须做出一些奇怪的决定来保持与非泛型集合的向后兼容性。

      【讨论】:

      • 当然不是。 ArrayLists 元素类型未定义为协变。
      猜你喜欢
      • 2014-06-09
      • 2011-02-13
      • 1970-01-01
      • 2020-03-11
      • 1970-01-01
      • 1970-01-01
      • 2011-05-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多