Java中的泛型传播

Java中的泛型传播,java,generics,Java,Generics,我有一个Java代码,其中包含非常棘手的泛型传播场景: public class Main { public static void parent(Parent<String> parent) {} public static void child(Child<String> parent) {} public static <T> Parent<T> makeParent() { return new Parent<

我有一个Java代码,其中包含非常棘手的泛型传播场景:

public class Main {

  public static void parent(Parent<String> parent) {}

  public static void child(Child<String> parent) {}

  public static <T> Parent<T> makeParent() {
    return new Parent<>();
  }

  public static void main(String[] args) {
    // this works
    parent(makeParent());

    // this works
    Parent<String> objectParent = makeParent();
    child(objectParent.child());

    // this works
    child(Main.<String>makeParent().child());

    // this does not work
    child(makeParent().child());
  }

  static class Parent<T> {

    public Child<T> child() {
      return new Child<>();
    }

  }

  static class Child<T> {}

}
公共类主{
公共静态无效父级(父级父级){}
公共静态无效子级(子级父级){}
公共静态父对象makeParent(){
返回新的父项();
}
公共静态void main(字符串[]args){
//这很有效
父(makeParent());
//这很有效
Parent objectParent=makeParent();
child(objectParent.child());
//这很有效
child(Main.makeParent().child());
//这行不通
child(makeParent().child());
}
静态类父类{
公共儿童(){
返回新的子对象();
}
}
静态类子{}
}
  • 我很好奇为什么以及它是如何工作的
    parent(makeParent())?如何推断T的替换

  • 以及为什么这不起作用
    child(makeParent().child())?当传播相同的泛型类型时


  • 关于调用链中的类型推断,需要记住的是,类型推断是在沿着调用链移动时进行的:如果您有
    a().b()

    • 首先对
      a()
      运行类型推断
    • 然后为
      a().b()
    因此:

  • parent(makeParent())
    :根据与
    parent()
    参数兼容的内容推断
    makeParent()的类型。因为它只接受父级
    ,所以这是推断的类型

  • child(makeParent().child())
    :推断
    makeParent()
    的类型;但是类型没有约束(它不是外部
    子项的参数),因此推断为
    父项
    ;然后
    makeParent().child()
    的类型是
    child
    ,它与
    child
    的参数类型不兼容,因此编译器错误

  • 令人恼火的是,Java没有推迟
    makeParent()
    的类型推断,直到它拥有更多信息,即
    makeParent().child()
    必须与某些特定类型兼容

    我认为这样做是为了限制推理的复杂性:我可以想象这样一种情况:需要解决一些极其复杂的类型推理约束集