【问题标题】:Generic Type Resolution - Compiler Steps泛型类型解析 - 编译器步骤
【发布时间】:2017-12-30 20:29:06
【问题描述】:

假设以下方法(Java 8):

public <T> List<Class<T>> getList() {
  return new ArrayList<>();
}

public <T> List<T> getList2() {
  return new ArrayList<>();
}

以下代码使用这些方法:

@Test
public void testLists() {
  getList().add(String.class); // Does not compile
  this.<String>getList().add(String.class); // Compiles
  getList2().add(String.class); // Compiles
}

第二个和第三个调用编译正常,而第一个给出:

列表中的add(java.lang.Class&lt;java.lang.Object&gt;) 不能应用于 add(java.lang.Class&lt;java.lang.String&gt;)


我不完全理解这里的解析步骤,也许有人可以解释为什么我需要类型见证并且编译器不会自动推断类型?

【问题讨论】:

    标签: java generics compiler-errors


    【解决方案1】:

    因为编译器不会/不能根据未来的方法调用推断通用参数。

    在您的情况下,当您调用 getList()getList2() 时,类型 T 已被推断为 Object。这意味着getList() 将返回一个List&lt;Class&lt;Object&gt;&gt; 对象,而您不能将Class&lt;String&gt; 对象添加到其中。

    在您的第三个语句中,您有 List&lt;Object&gt;,因此您可以向其中添加 Class&lt;String&gt;

    【讨论】:

    • 嗯好的,我明白了,谢谢你的简单解释。
    • 但这不是一些“未来”的调用,在更下面几行。它是立即调用,紧随其后的是一个立即点。
    • @user1589188,是的,它现在不适用于链式方法调用,但它是 JEP 的一部分:openjdk.java.net/jeps/101
    • @Codebender 我咯咯地笑着看到它是“101”,但它还没有。
    【解决方案2】:

    总之,StringObject,而Class&lt;String&gt; 不是Class&lt;Object&gt;

    参考:javadoc

    【讨论】:

      【解决方案3】:

      使用类似的东西代替:

      getList().add(String.class);
      
      <String>getList().add(String.class);
      for
       public <T> List<Class<T>> getList() {
        return new ArrayList<>();
      }
      

      现在调用它时,参数和返回类型必须匹配。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-05
        • 2012-12-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多