繁体   English   中英

Java:实例化没有默认构造函数的泛型类

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM