将Generic转换为其子类

时间:2013-08-05 23:49:31

标签: java android generics casting

所以,我正在尝试为android sqlite创建一个小型库,我已经掌握了大部分基本功能,但我遇到的问题是将结果作为特定类返回。我有

abstract public class Table<RowClass extends Row>{
    public List<RowClass> fetchAll() {
        //Fetch the stuff here
        //In the while class to add each row to the array
        RowClass row = (RowClass) new Row();
    }
}

但是每当我尝试记录row.getClass()。getName()时,它总是以Row形式返回,而不是RowClass,它的行为与Row类似,而不是RowClass。如何将它转换为RowClass?

编辑:从表

扩展的内容
public class SourcesTable<Rowclass extends Row> extends Table<Row>
{
    public String getName()
    { return "sources"; }

    public String[] getAllColumns()
    {
        String[] columns = { "name" };
        return columns;
    }
}

我用

实例化它
Tables sourcesTable = new SourcesTable<SourcesRow>();
List<SourcesRow> list = sourcesTable.fetchAll();

其中

public class SourcesRow extends Row
{
    public String toString()
    { return this.data.get("name"); }
}

public class Row
{
    public String toString()
    { return ""; }
}

很抱歉,如果这令人困惑,我正在学习Java来自PHP,所以我可能会以错误的方式解决这个问题,我只是不习惯严格的类型转换

1 个答案:

答案 0 :(得分:2)

这是您的相关代码(您发布的其余代码实际上是不必要的:)):

abstract public class Table<RowClass extends Row>{
    public List<RowClass> fetchAll() {
        //Fetch the stuff here
        //In the while class to add each row to the array
        RowClass row = (RowClass) new Row();
    }
}

您要问的是如何创建RowClass的新实例。你不能。 Java不提供有关RowClass类型的信息。由于类型擦除,在运行时不存在有关作为通用参数传递的类型的信息。如果要实例化泛型参数类型的对象,则必须以另一种方式提供该类。例如(为清楚起见,遗漏了异常处理):

abstract public class Table<RowClass extends Row>{
    private final Class<RowClass> rowClass; // holds the Class of each row
    public Table (Class<RowClass> rowClass) {
        this.rowClass = rowClass;
    }
    public List<RowClass> fetchAll() {
        //Fetch the stuff here
        //In the while class to add each row to the array
        RowClass row = rowClass.newInstance();
    }
}

然后将Whatever.class传递给Table构造函数(表是抽象的,因此在您的情况下,您的子类必须将其行的类传递给超级构造函数),例如:

// assume: SpecialRow and MyCustomRow are concrete classes extending Row
// and defined elsewhere.

// scenario 1 - subclass knows row type
public class SpecialTable extends Table<SpecialRow> {
    public SpecialTable () {
        super(SpecialRow.class);
    }
}

// scenario 2 - subclass still lets user specify row type
public class CustomTable <R extends Row> extends Table<R> { 
    public CustomTable (Class<R> rowClass) { 
        super(rowClass);
    }
}

// usage:
SpecialTable special = new SpecialTable();
CustomTable<MyCustomRow> custom = new CustomTable<MyCustomRow>(MyCustomRow.class);

您也可以将该类传递给fetchAll,例如:

public List<RowClass> fetchAll(Class<RowClass> rowClass) {
    //Fetch the stuff here
    //In the while class to add each row to the array
    RowClass row = rowClass.newInstance();
}

甚至传递一个对象(类似于通用toArray()的工作方式),如:

public List<RowClass> fetchAll(RowClass refObject) {
    //Fetch the stuff here
    //In the while class to add each row to the array
    RowClass row = refObject.getClass().newInstance();
}

了解更多信息:

编辑:如果我猜测你要做的事情是正确的,那么这里有另一种设计方法。

因为Table是抽象的,所以我觉得您正在尝试创建Table子类,其中子类具有自己的特定行类型。在这种情况下,上面的第一个选项(将类类型传递给超级构造函数)将是最合适的。但是,您可能希望考虑让子类实例化自己的已知Row类,并提供允许基类执行此操作的抽象方法,而不是完成所有这些操作,例如:

abstract public class Table { // no generics necessary
    // subclasses must override this
    abstract protected Row newRow ();
    // the base class can use newRow() to let the subclass determine the type
    public List<Row> fetchAll () {
        // in the while loop to add each row to the array:
        Row row = newRow();
    }
}

这种方法的主要优点是让知道其特定Row子类的Table子类按其认为合适的方式构造其Row子类。

希望有所帮助。