[英]Java: Instantiating a generic class with no default constructor
我想这样做:
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
参数。
如何才能做到这一点?
我也在这里问了一个跟进问题 。 如果你能回答这个问题,我将不胜感激。
这个问题是相关的,但只有在假定类具有默认构造函数时才有意义。
已经说过,你不能用new
创建一个T实例,所以我会使用Factory Pattern或Prototype Pattern
因此,您的构造函数看起来像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());
}
不应该这样做的好理由是,你不能强迫子类实现某个构造函数。 对于接口的实现来说非常明显,因为它们不包含构造函数的契约。
如果您的真实或抽象类BaseTable
有一个构造函数BaseTable(int columns)
, VectorTable
带有单个列的虚构子类VectorTable
就不需要实现它并且可以做一些像
public VectorTable(int intialValue) {
super(1);
this.initialValue = initialValue;
}
首先,你不知道T
实现了构造函数,其次,你不知道构造函数是否具有相同的目的( 它应该在正确的代码中真正具有!! )
所以我认为,更好的解决方案是将参数化部分从构造函数移动到单独的(final?)方法中,使用默认构造函数创建实例并在之后调用该初始化方法。
如果要确保所有BaseTable子类始终正确初始化,您可以考虑实现BaseTableFactory
。
编辑
并且new T()
(实例化默认构造函数)也是不可能的,因为没有类可以强制实现可访问的默认构造函数。 我仍然认为,工厂模式是你最好的朋友。
您需要使用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);
PS这不是我原来的解决方案。 我很久以前就找到了它并在我的代码中使用它。 不幸的是,我无法找到原始想法的链接......
简单!
使用静态工厂方法而不是构造函数:
public static <T extends TableEntry> newInstance(int rows, int cols) {
return new BaseTable<T>(rows, cols);
}
实例化类型
BaseTable<Number> = BaseTable.newInstance(10, 20);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.