为什么编译器不能推断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()