6

我正在尝试使用 Builder 模式而不是伸缩构造函数来创建一个具有许多参数的类。我正在按照 Joshua Bloch 的 Effective Java 描述的方式执行此操作,在封闭类上有私有构造函数,以及一个公共静态 Builder 类。Builder 类确保对象在调用 build() 之前处于一致状态,此时它将封闭对象的构造委托给私有构造函数。因此

public class Foo {

    // Many variables

    private Foo(Builder b) {
        // Use all of b's variables to initialize self
    }

    public static final class Builder {

        public Builder(/* required variables */) {

        }

        public Builder var1(Var var) {
            // set it
            return this;
        }

        public Foo build() {
            return new Foo(this);
        }

    }

}

然后我想为一些变量添加类型边界,因此需要对类定义进行参数化。我希望 Foo 类的边界与 Builder 类的边界相同。

public class Foo<Q extends Quantity> {

    private final Unit<Q> units;
    // Many variables

    private Foo(Builder<Q> b) {
        // Use all of b's variables to initialize self
    }

    public static final class Builder<Q extends Quantity> {
        private Unit<Q> units;

        public Builder(/* required variables */) {

        }

        public Builder units(Unit<Q> units) {
            this.units = units;
            return this;
        }

        public Foo build() {
            return new Foo<Q>(this);
        }

    }

}

这编译得很好,但是编译器允许我做我认为应该是编译器错误的事情。例如

public static final Foo.Builder<Acceleration> x_Body_AccelField =
        new Foo.Builder<Acceleration>()
        .units(SI.METER)
        .build();

这里的 units 参数不是Unit<Acceleration>but Unit<Length>,但它仍然被编译器接受。

我在这里做错了什么?我想确保在编译时单元类型正确匹配。

4

2 回答 2

7

units应该归来Builder<Q>,而不是一蹶不振Builder

于 2010-05-17T22:27:53.127 回答
0

尽管@Daniel 的观点是有效的,但至少 Eclipse 仍然发现了代码中的错误。当然,您对Quantity,Unit和的定义METER可能与我放在一起的简单技巧不同:

interface Quantity {
}
class Acceleration implements Quantity {
}
class Length implements Quantity {
}
public class Unit<Q extends Quantity> {
    public static final Unit<Length> METER = new Unit<Length>();
}

public static final Foo.Builder<Acceleration> x_Body_AccelField =
    new Foo.Builder<Acceleration>()
    .units(Unit.METER) // here the compiler complains
    .build();

错误信息是:

The method units(Unit<Acceleration>) in the type Foo.Builder<Acceleration> is
not applicable for the arguments (Unit<Length>)
于 2010-05-17T22:47:23.097 回答