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

标签 java generics language-lawyer type-inference inner-classes

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

因此问题仍然被报告为“找不到 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(),也会出现同样的问题

关于java - 为什么编译器无法推断 Java 中内部类的泛型类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67738489/

相关文章:

java - 将泛型类型对象写入 java 文件

具有关联类型错误的 Swift 协议(protocol)

c - 外部静态声明 - K&R2

c++ - 将 char16_t 分配给基本多语言平面之外的字 rune 字代码点

java - 实例化新内部类时,内部类不是公共(public)错误

java - 为什么 Redis 不在 __keyevent@*__ :expired topic events? 上调用我的 MessageListener

java - 调用 Query.uniqueResult() 时出现 ClassCastException

java - Guava 为什么 toStringFunction 不是泛型函数?

Java检查图像是否具有透明度

c++ - 是否可以将大括号括起来的初始化程序作为宏参数传递?