当我尝试这样的事情时
public class Example<T> {
private T value;
private Example() {
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
public static <T> Builder<T> builder() {
return new Builder<>();
}
public static class Builder<T> {
public Example<T> build() {
return new Example<>();
}
}
public static void main(String[] args) {
Example<String> example = Example.builder().build();
example.setValue("test");
System.out.println(example.getValue().toUpperCase());
}
}
我收到错误
Example.java:27: error: incompatible types: Example<Object> cannot be converted to Example<String>
Example<String> example = Example.builder().build();
但是当我将类型添加到builder
方法的参数时,一切正常
public static <T> Builder<T> builder(T type) {
return new Builder<>();
}
为什么?以及如何摆脱这种虚拟类型参数?
奖金问题:如何将复杂类型传递给这样的方法?
public static <T> Builder<T> builder(Class<T> type) {
return new Builder<>();
}
Example<Optional<String>> example = Example.builder(???).build();
UPDATE:这只是一个例子。现实生活中的应用程序将有多个构建器在构建过程的不同阶段相互创建,当然,他们将具有接受通用类型的方法。我希望有一种方法可以帮助编译器推断类型。我什至同意反思的技巧,如果有的话,它们可以帮助我获得漂亮的DSL。
Example
是原始类,因此T
隐式为Object
。您可以在调用方法时指定通用类型,方法是在方法调用之前将其放在尖括号(<>
)中:
Example<String> example = Example.<String>builder().build();
// Here --------------------------^
编译器可以推断出您要创建的Example
是Example<String>
,但无法推断出Builder
方法返回的builder()
应该是Builder<String>
。
您可以通过将语句分成两个语句来帮助编译器:
Builder<String> builder = Example.builder();
Example<String> example = builder.build();
或通过指定您希望从Builder
方法获得的builder()
的类型:
Example<String> example = Example.<String>builder().build();
使用lombok依赖项并使用@Builder批注。这样可以省很多麻烦
如果您不介意未检查的作业警告,您可以仅添加以下更改:
public static Builder builder() {
return new Builder<>();
}
编辑开始:
此外,如果要省略警告,可以将Builder
类更改为:
public static class Builder {
private <T> Example<T> build() {
return new Example<>();
}
}
并将静态Builder
方法更改为:
public static Builder builder() {
return new Builder();
}
编辑结束。
然后您可以像这样使用它:
Example<String> example = Example.builder().build();