Java Builder pattern with Generic type bounds

Posted by I82Much on Stack Overflow See other posts from Stack Overflow or by I82Much
Published on 2010-05-17T22:23:06Z Indexed on 2010/05/17 22:30 UTC
Read the original article Hit count: 566

Hi all,

I'm attempting to create a class with many parameters, using a Builder pattern rather than telescoping constructors. I'm doing this in the way described by Joshua Bloch's Effective Java, having private constructor on the enclosing class, and a public static Builder class. The Builder class ensures the object is in a consistent state before calling build(), at which point it delegates the construction of the enclosing object to the private constructor. Thus

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);
        }

    }

}

I then want to add type bounds to some of the variables, and thus need to parametrize the class definition. I want the bounds of the Foo class to be the same as that of the Builder class.

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);
        }

    }

}

This compiles fine, but the compiler is allowing me to do things I feel should be compiler errors. E.g.

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

Here the units argument is not Unit<Acceleration> but Unit<Length>, but it is still accepted by the compiler.

What am I doing wrong here? I want to ensure at compile time that the unit types match up correctly.

© Stack Overflow or respective owner

Related posts about java

Related posts about generics