2010-01-21 126 views
4

我試圖做到這一點:的Java:實例化一個泛型類沒有默認構造函數

public class BaseTable<T extends TableEntry> 

{ 

    protected int mRows; 
    protected int mCols; 
    protected ArrayList<T> mEntries; 

    public BaseTable(int rows, int cols) 
    { 
     mRows = rows; 
     mCols = cols; 
     mEntries = new ArrayList<T>(); 
     for (int i = 0; i < rows; i++) 
     { 
      mEntries.add(new T(cols)); //this obv. doesn't work 
     } 
    } 
} 

實例化泛型比較辛苦,因爲它是,但什麼使這更困難的是,T這裏沒有一個默認的構造函數,它的構造函數只需要一個參數int

這怎麼辦?


我在這裏也詢問了follow up question。如果你能回答這個問題,我會很感激。

question是相關的,但只有在類別被假定爲具有默認構造函數的情況下才是相關的。

回答

5

有人說過,你不能創建T的實例與new,所以 我會使用工廠模式或原型模式

所以你的構造看起來像 public BaseTable(int rows, int cols, LineFactory factory)用適當的實例的工廠。

就你而言,我更喜歡原型模式,因爲你的TableEntry對象可能非常輕。您的代碼如下所示:

public BaseTable(int rows, int cols, T prototype) 
{  
    mRows = rows; 
    mCols = cols; 
    prototype.setColumns(cols); 
    mEntries = new ArrayList<T>(); 
    for (int i = 0; i < rows; i++) 
    { 
    @SuppressWarnings("unchecked") 
    T newClone = (T)prototype.clone(); 
    mEntries.add(newClone); //this obv. does work :) 
    } 
} 

public static void main(String[] args) 
{ 
    new BaseTable<SimpleTableEntry>(10, 2, new SimpleTableEntry()); 
} 
3

爲什麼它不應該不應該這樣做是因爲你不能強制子類實現某個構造函數。接口的實現非常明顯,因爲它們不包含構造函數的合同。

如果你的真實的或抽象類BaseTable有一個構造函數BaseTable(int columns),在虛構的子類VectorTable與單個列就不需要實現,而且可以做壞事一樣

public VectorTable(int intialValue) { 
    super(1); 
    this.initialValue = initialValue; 
} 

因此,首先,你不知道是不是T實現構造函數在所有第二,你不知道如果構造有着異曲同工之妙(它真的應該有正確的代碼!

因此,我認爲,一個更好的解決方案s將參數化部分從構造函數移動到單獨的(final?)方法中,使用默認構造函數創建實例並在之後調用該初始化方法。

如果您想確保所有BaseTable子類始終正確初始化,您可能會考慮實施BaseTableFactory

編輯

而且new T()(實例默認構造函數)是不可能的爲好,因爲不用上課可以被迫實現無障礙默認構造函數。我仍然認爲,工廠模式是你最好的朋友。

+1

**和**,'T'可以是抽象類或接口。在這種情況下,在任何情況下都不能直接*實例化。 –

-1

簡單!

使用靜態工廠方法代替構造函數:

public static <T extends TableEntry> newInstance(int rows, int cols) { 
    return new BaseTable<T>(rows, cols); 
} 

要實例類型

BaseTable<Number> = BaseTable.newInstance(10, 20); 
1

您需要使用Factory接口:

public interface TableEntryFactory<T extends TableEntry>{ 
public T create (int cols); 
} 

你也需要做每類「T型」工廠:

// for every class of type T 
public class SpecialTableEntry extends TableEntry{ 
    SpecialTableEntry(int cols){ 
     ... 
    } 
} 

// make a factory creating instance of this class 
public class SpecialTableEntryFactory implements TableEntryFactory<SpecialTableEntry> { 
    @Override 
    public SpecialTableEntry create (int cols){ 
     return new SpecialTableEntry(cols); 
    } 
} 

你的代碼如下:

public class BaseTable<T extends TableEntry> 

{ 

protected int mRows; 
protected int mCols; 
protected ArrayList<T> mEntries; 

public BaseTable(int rows, int cols, TableEntryFactory<T> tableFactory) 
{ 
    mRows = rows; 
    mCols = cols; 
    mEntries = new ArrayList<T>(); 
    for (int i = 0; i < rows; i++) 
     { 
     mEntries.add(tableFactory.create(cols)); //this should work now 
     } 
    } 
} 


你可以這樣調用它:

TableEntryFactory<SpecificTableEntry> myFactory = new SpecificTableEntryFactory(); 
BaseTable<?> table = new BaseTable<SpecificTableEntry>(rows,cols,myFactory); 


附:這不是我原來的解決方案。我很久以前就在其中找到它,並將其用於我的代碼中。不幸的是,我找不到原始想法的鏈接...

相關問題