2010-05-17 81 views
5

我試圖用許多參數創建一個類,使用Builder模式而不是伸縮構造函數。我按照Joshua Bloch的Effective Java描述的方式進行操作,在封閉類上有私有構造函數,還有一個公共靜態生成器類。在調用build()之前,Builder類確保對象處於一致狀態,此時它將封閉對象的構造委託給私有構造函數。因此,具有泛型類型邊界的Java生成器模式

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

這裏單位的說法是不Unit<Acceleration>但​​,但它仍然是由編譯器所接受。

我在這裏做錯了什麼?我想在編譯時確保單元類型正確匹配。

回答

6

units應該返回Builder<Q>,而不是一個ungenerified Builder

+0

謝謝你,我沒有想到的很清楚這方面。 – I82Much 2010-05-17 22:39:37

0

儘管@ Daniel的觀點是有效的,但是至少在Eclipse中發現代碼中的錯誤。當然,你的QuantityUnitMETER定義是從簡單的黑客我放在一起可能不同:

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>) 
+0

有趣。我使用的是NetBeans,並沒有抱怨。我使用的單位等級體系來自JSR 275(http://download.java.net/maven/2/net/java/dev/jsr-275/jsr-275/1.0-beta-2/)和JScience (http://jscience.org/) – I82Much 2010-05-17 23:32:54

+2

即使在NetBeans中,你也應該得到這個錯誤......如果不是的話,那是一個非常糟糕的錯誤。原始代碼的區別在於你有一箇中間屬性:新的Foo.Builder ()。cheese(GOUDA).units(Unit.METER),其中'cheese'方法返回Builder Builder Builder 。 – Cowan 2010-05-18 02:04:42