为什么编译器无法推断 Java 中内部 class 的泛型类型?

Why compiler cannot infer generic types of the inner class in Java?

class A<T>
{
    class InnerA<U>
    {}
}

public class Main
{
    public static void main(String[] args)
    {
        A<Integer>.InnerA<String> var = new A<>().new InnerA<>();
    }
}

编译上述代码片段时,会导致编译时错误,提示“不兼容的类型:无法推断 A.InnerA<> 的类型参数。在我看来,编译器应该能够推断类型成为 InnerA<String>.

为什么不能这样做?如果有人可以解释它是如何在幕后工作的,那将会很有帮助。

编译器错误消息具有误导性。

编译器只能从赋值的左侧推断表达式的类型,前提是表达式是其结果实际被赋值的表达式。在您的示例中,new A<>() 未分配,而仅用于内部 class¹ 的合格实例化。由于 new A<>() 没有赋值上下文,编译器推断 new A<Object>().

对于 .new InnerA<>(),有一个赋值上下文,编译器尝试使用赋值的左侧来推断结果类型但失败了,因为 A 的类型已经不兼容。在缩短的编译器消息中,无法推断 InnerA 的类型是可见的,但不是 A.

的类型参数不匹配的原因

长错误信息看起来像

Main.java:11: error: incompatible types: cannot infer type arguments for A.InnerA<>
        A<Integer>.InnerA<String> var = new A<>().new InnerA<>();
                                                            ^
  reason: no instance(s) of type variable(s) U exist
          so that A<Object>.InnerA<U> conforms to A<Integer>.InnerA<String>

  where U is a type-variable:
    U extends Object declared in class A.InnerA

所以问题仍然被报告为“找不到 U 的类型”,但我们也可以看到更深层次的原因是没有 U 可以解决 A<T>.

类型不匹配的问题

我们还可以通过将行更改为

来证明实际原因
A<Integer>.InnerA<String> var = new A<>().new InnerA<String>();

InnerA 提供正确的类型,现在得到

incompatible types:
    A<Object>.InnerA<String> cannot be converted to A<Integer>.InnerA<String>

或将行更改为

A<Integer>.InnerA<String> var = new A<Integer>().new InnerA<>();

这将解决问题,因为现在 A 具有正确的类型,并且可以从左侧推断出 InnerA 的类型。


¹ 如果您 genericMethod1().method2()

也会出现同样的问题