首页 文章

Java中的泛型类型推断限制

提问于
浏览
7

我在使用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<> ,则有效 .

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

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

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

2 回答

  • 5

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

    通用类型检查是一个单独的概念 . 一般情况下,检查器看不到推断类型( <> 推断为 <String, String> )和显式类型(代码中写入 <String, String> )之间的区别,无论是哪种方式,您的类都应该是类型安全的 .

  • 1

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

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

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

    没有 .

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

    它们完全不相关 .

相关问题