我在使用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泛型类型推断有哪些限制?它只解析构造函数或静态方法中提供的类型吗?我没有找到任何关于此的文件。
如果我们不能使用类型推断,这是否意味着该类可能不是类型安全的?
答案 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>
)之间的差异,无论是哪种方式,它都要检查只有字符串与该对象一起使用。只要编译器没有抱怨,你的类应该是类型安全的。