Java中的泛型类型推断限制

时间:2018-05-23 12:07:16

标签: java generics types type-inference

我在使用Java泛型类型推断的项目中面临以下问题。这是一个与我原来的代码示例相似的代码示例:

public class BuildableObject<R, S> {
  public static class OneParameter<R> { }
  public static class TwoParameters<R, S> { }
  interface TwoParamInterface<R, S> { }
  public static class Implementer<T> implements TwoParamInterface<T, T> {}

  private final OneParameter<R> first;
  private final OneParameter<S> second;
  private final TwoParameters<R, S> third;
  private final TwoParamInterface<R, S> fourth;

  private BuildableObject(OneParameter<R> first, OneParameter<S> second, TwoParameters<R, S> third, TwoParamInterface<R, S> fourth) {
    this.first = first;
    this.second = second;
    this.third = third;
    this.fourth = fourth;
  }

  public static class Builder<R, S> {
    private OneParameter<R> first = null;
    private OneParameter<S> second = null;
    private TwoParameters<R, S> third = null;
    private TwoParamInterface<R, S> fourth = null;

    public Builder() {}

    public Builder<R, S> first(OneParameter<R> first) {
      this.first = first; return this;
    }

    public Builder<R, S> second(OneParameter<S> second) {
      this.second = second; return this;
    }

    public Builder<R, S> third(TwoParameters<R, S> third) {
      this.third = third; return this;
    }

    public Builder<R, S> fourth(TwoParamInterface<R, S> fourth) {
      this.fourth = fourth; return this;
    }

    public BuildableObject<R, S> build() {
      return new BuildableObject<>(first, second, third, fourth);
    }
  }

  public static void main(String... args) {
    new Builder<>()
        .first(new OneParameter<>())
        .second(new OneParameter<>())
        .third(new TwoParameters<>())
        .fourth(new Implementer<String>())
        .build();
  }
}

此代码在new Implementer<String>处断开,但如果我使用new Builder<String, String>而不是new Builder<>,则会有效。

如果在Builder<String, String>中指定了R和S的类型,为什么Java不能推断出Builder的类型是new Implementer<String>

Java泛型类型推断有哪些限制?它只解析构造函数或静态方法中提供的类型吗?我没有找到任何关于此的文件。

如果我们不能使用类型推断,这是否意味着该类可能不是类型安全的?

2 个答案:

答案 0 :(得分:6)

https://docs.oracle.com/javase/specs/jls/se9/html/jls-18.html详细记录了这一点。但问题在于它详细记录了 :除非你阅读有关这一主题的论文,否则你不太可能熟悉许多行话。

对于这种情况,您只需要了解对于类型推断,在new Builder<>()之后调用哪种方法并不重要;仅使用构造函数本身的参数(以及目标类型,例如Builder<String, String> b = new Builder<>();中的目标类型,但在这种情况下,您没有参数)。

  

它只解析构造函数或静态方法中提供的类型吗?

没有

  

如果我们不能使用类型推断,这是否意味着该类可能不是类型安全的?

他们完全不相关。

答案 1 :(得分:1)

当代码太复杂时,通用类型推断可能会失败,但通常您可以显式指定类型,以便不需要推理。链式方法调用有时会导致这种情况。这只是意味着你不必自己指定类型。

通用类型检查是一个单独的概念。通常,检查器看不到推断类型(<>推断为<String, String>)和显式类型(代码中写入的<String, String>)之间的差异,无论是哪种方式,它都要检查只有字符串与该对象一起使用。只要编译器没有抱怨,你的类应该是类型安全的。