为什么编译器不能推断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<>()未分配,而仅用于内部类¹的合格实例化。由于没有 的赋值上下文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

所以问题仍然报告为“ can't find a type forU ”,但我们也可以看到更深层次的原因是 noU永远无法解决类型不匹配的问题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()


以上是为什么编译器不能推断Java内部类的泛型类型?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>