Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有泛型类型边界的Java Builder模式_Java_Generics_Builder_Type Safety - Fatal编程技术网

具有泛型类型边界的Java Builder模式

具有泛型类型边界的Java Builder模式,java,generics,builder,type-safety,Java,Generics,Builder,Type Safety,我正在尝试创建一个具有许多参数的类,使用构建器模式,而不是伸缩构造函数。我正以Joshua Bloch的高效Java所描述的方式来做这件事,在封闭类上有私有构造函数,还有一个公共静态构建器类。Builder类在调用build()之前确保对象处于一致状态,此时它将封闭对象的构造委托给私有构造函数。因此 public class Foo { // Many variables private Foo(Builder b) { // Use all of b's v

我正在尝试创建一个具有许多参数的类,使用构建器模式,而不是伸缩构造函数。我正以Joshua Bloch的高效Java所描述的方式来做这件事,在封闭类上有私有构造函数,还有一个公共静态构建器类。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);
        }

    }

}
公共类Foo{
私人最终单位;
//多变量
私人建筑事务主任(建筑商b){
//使用b的所有变量初始化self
}
公共静态最终类生成器{
私人单位;
公共生成器(/*必需变量*/){
}
公共建筑单位(单位){
这个。单位=单位;
归还这个;
}
公共Foo build(){
返回新的Foo(本);
}
}
}
这可以很好地编译,但是编译器允许我做一些我认为应该是编译器错误的事情。例如

public static final Foo.Builder<Acceleration> x_Body_AccelField =
        new Foo.Builder<Acceleration>()
        .units(SI.METER)
        .build();
公共静态最终Foo.Builder x_Body_Accel字段=
新建Foo.Builder()
.单位(国际单位制米)
.build();
这里的units参数不是
Unit
,而是
Unit
,但编译器仍然接受它


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

单元
应该返回
Builder
,而不是一个未泛化的
Builder
尽管@Daniel的点是有效的,但Eclipse至少发现了代码中的错误。当然,你对
数量
单位
的定义可能不同于我所说的简单化:

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();
接口数量{
}
类加速实现数量{
}
类长度表示数量{
}
公营课组{
公共静态最终单位仪表=新单位();
}
公共静态最终Foo.Builder x_Body_AccelField=
新建Foo.Builder()
.units(Unit.METER)//编译器在这里抱怨
.build();
错误消息是:

The method units(Unit<Acceleration>) in the type Foo.Builder<Acceleration> is
not applicable for the arguments (Unit<Length>)
Foo.Builder类型中的方法单位(Unit)为
不适用于参数(单位)

很有趣。我使用的是NetBeans,它没有抱怨。我使用的单元etc层次结构来自jsr275()和JScience(),即使在NetBeans中,您也应该会遇到这个错误。。。如果不是,那是一个非常糟糕的错误。原始代码的不同之处在于,如果您有一个中间属性:new Foo.Builder().cheese(GOUDA).units(Unit.METER),其中“cheese”方法返回的是Builder而不是Builder。