简体   繁体   English

Generics 在 Java 中传播

[英]Generics propagation in Java

I have a Java code with quite tricky generics propagation scenario:我有一个 Java 代码具有相当棘手的 generics 传播场景:

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> {}

}
  1. I am curious why and how this works parent(makeParent());我很好奇为什么以及如何工作parent(makeParent()); ? ? How replacement for T is inferred?如何推断 T 的替换?

  2. And also why this does not work child(makeParent().child());还有为什么这不起作用child(makeParent().child()); ? ? As the same generic type is propagated.因为相同的泛型类型被传播。

The thing to remember about type inference in call chains is that the type inference is done as you move along the chain: if you have a().b() :关于调用链中的类型推断要记住的是,类型推断是在您沿着链移动时完成的:如果您有a().b()

  • Type inference is run for a() first;首先为a()运行类型推断;
  • Then a type is inferred for a().b()然后为a().b()推断出一个类型

So:所以:

  1. parent(makeParent()) : the type of makeParent() is inferred according to what is compatible with the parameter of parent() . parent(makeParent()) : makeParent() () 的类型是根据与parent()的参数兼容的情况来推断的。 Since that will only accept a Parent<String> , that's the inferred type.由于那只会接受Parent<String> ,这就是推断的类型。

  2. child(makeParent().child()) : the type of makeParent() is inferred; child(makeParent().child()) :推断makeParent()的类型; but there are no constraints on the type (it's not the parameter to the outer child ), so it's inferred to be Parent<Object> ;但是对类型没有限制(它不是外部child的参数),因此推断为Parent<Object> then the type of makeParent().child() is Child<Object> , which isn't compatible with the parameter type of child , hence the compiler error.那么makeParent().child()的类型是Child<Object> ,它与child的参数类型不兼容,因此编译器错误。

It's annoying that Java doesn't defer the type inference of makeParent() until it has more information, namely the fact that makeParent().child() has to be compatible with some particular type.令人讨厌的是 Java 没有推迟makeParent()的类型推断,直到它有更多信息,即makeParent().child()必须与某些特定类型兼容这一事实。

I suppose this is done to limit the complexity of the inference: I can imagine a situation where some obscenely complex set of type inference constraints could need to be solved.我想这样做是为了限制推理的复杂性:我可以想象需要解决一些极其复杂的类型推理约束集的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM