2010-01-21 78 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); 


附:这不是我原来的解决方案。我很久以前就在其中找到它,并将其用于我的代码中。不幸的是,我找不到原始想法的链接...

相关问题