构建器模式中的 java 类型推断

标签 java generics design-patterns type-inference builder

我想创建一个参数化(通用)类MyType<T>及其 builder 。构建器将有一些忽略类型 T 的方法以及一些使用该类型的方法。但似乎使用这种模式我必须重复 T声明:

                     how to omit this declaration?
                                   |
                                   V
MyType<String> myType = Builder.<String>of()
                               .method1(argument_can_be_of_any_type)
                               .method2(argument_must_be_of_type_T = String)
                               .build();

是否可以使用一些java语法技巧或其他设计模式来省略第二个类型声明并使API更加用户友好?例如:

List<String> aList = Lists.emptyList();

List<String> aList = new LinkedList<>();   

我不想在构建器中强制执行任何方法顺序

最佳答案

由于我最初的答案并不像广告中所说的那样有效,所以我对事情进行了一些修改。 (感谢 shmosel 发现问题,感谢 Daniel Pryden 提供建议的解决方案。)

/* contents of Box.java */
public class Box<T>
{
    private T contents;
    private Object data;

    protected Box(T contents, Object data) {
        this.contents = contents;
        this.data = data;
    }

    public static BoxBuilder builder() {
        return new BoxBuilder();
    }

    public T getContents() {
        return contents;
    }
}

/* contents of BoxBuilder.java */
public class BoxBuilder
{
    private Object data;

    public BoxBuilder withAnything(Object o) {
        this.data = o;
        return this;
    }

    // Infers new type from argument
    public <T> TypedBoxBuilder<T> withBoxContent(T contents) {
        TypedBoxBuilder<T> builder = new TypedBoxBuilder<T>();
        builder.setData(data);
        builder.setContents(contents);

        return builder;
    }
}

/* contents of TypedBoxBuilder.java */
public class TypedBoxBuilder<T>
{
    private T contents;
    private Object data;

    public TypedBoxBuilder() {
    }

    public TypedBoxBuilder<T> withAnything(Object data) {
        this.data = data;
        return this;
    }

    public TypedBoxBuilder<T> withContents(T contents) {
        this.contents = contents;
        return this;
    }

    public Box<T> build() {
        return new Box<T>(contents, data);
    }

    public void setContents(T contents) {
        this.contents = contents;
    }

    public void setData(Object data) {
        this.data = data;
    }
}

这是客户端代码:

Box<String> box = Box.builder() // Returns BoxBuilder
        .withBoxContent("FOO") // Returns TypedBoxBuilder<String>
        .withAnything(42) // Returns TypedBoxBuilder<String>
        .build(); // Returns Box<String>
String c = box.getContents();

这也有效:

Box<String> box = Box.builder() // Returns BoxBuilder
        .withAnything(42) // Returns BoxBuilder
        .withBoxContent("FOO") // Returns TypedBoxBuilder<String>
        .build(); // Returns Box<String>
String c = box.getContents();

关于构建器模式中的 java 类型推断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45362662/

相关文章:

Java 泛型 : getting rid unchecked cast warning (case described inside)

java - 没有警告的通用接口(interface)比较器

c# - 时间表 : Retrieve data using SQL, LINQ 或类?

Java:将匿名类带到外面

java - 在Java中删除Cookie/浏览器如何删除Cookie

java - 在另一个线程中等待 Future 结果

java - java中的垃圾收集是特定于某个JVM的,如果一个JVM中的应用程序发生内存泄漏,其他JVM会发生什么情况

c# - 基于类类型创建泛型

java - 如何从其父类(super class)型列表中返回对象作为其类型?

C# 替换巨大的 if-else 语句