在子类化(和静态方法)中使用泛型的Java

时间:2017-02-20 19:53:09

标签: java generics inheritance

以下是一个清理过的示例,将此内容简化为单个问题。有3个类文件(其中有一些类shell)。什么行不通的是在getTable()类中getCreateTableList()SpanTable中的每一个上的第一个参数。我想知道如何使该参数具有其原始的Span/SpanTable子类类型并传递给DbTable调用?或者实际上,DbTable并不需要额外的信息,但我希望SpanTable或任何调用者保留其类型。

DbRow:

public class DbRow {
    static class Span extends DbRow {}
}

DBTABLE:

import java.util.ArrayList;

abstract public class DbTable<R extends DbRow> {  

    static class PairList<L, R> { 
        public void addEntry(L s, R t) {  }
        public R getRightForLeft(L left) { return null; }
    }
    static class DbPlatform {  }
    static class DbSelectStatement {    }
    public static class Span extends DbRow { }
    static class TableList<R extends DbRow, T extends DbTable<R>> extends ArrayList<T> {}
    static class PlatformTableList<R extends DbRow, T extends DbTable<R>> 
                    extends PairList<DbPlatform, TableList<R, T>> {}
    static DbSelectStatement getDefaultQuery(String tableName) { return null; }

    public DbTable(DbPlatform platform, String tableName) { }
    public DbSelectStatement getStatement() { return null; }

    /** Return the matching DbTable with matching DbSelectStatement or null */
    static protected DbTable<DbRow> getTable(
            PlatformTableList<DbRow, DbTable<DbRow>> platformList, 
            DbPlatform platform, DbSelectStatement stmt) {
        // Get the table from the list, or create new
        TableList<DbRow, DbTable<DbRow>> list = 
                getCreateTableList(
                 (PlatformTableList<DbRow, DbTable<DbRow>>) platformList, platform);
        // Search the list for a match
        for(DbTable<DbRow> table : list) 
            if(table.getStatement().equals(stmt))
                return table;
        return null; 
    }

    /** Get or create and return a TableList for the Platform.  */
    static protected TableList<DbRow, DbTable<DbRow>> getCreateTableList(
            PlatformTableList<DbRow, DbTable<DbRow>> platformList, DbPlatform platform) { 

        TableList<DbRow, DbTable<DbRow>> list = (TableList<DbRow, DbTable<DbRow>>) 
                platformList.getRightForLeft(platform);
        if(list == null) {
            list = new TableList<DbRow, DbTable<DbRow>>();
            platformList.addEntry(platform, list); 
        }
        return list;
    }
}

SpanTable:

class SpanTable<R extends DbTable.Span> extends DbTable<R> { 

    static private PlatformTableList<Span, SpanTable<Span>> platformList = 
            new PlatformTableList<Span, SpanTable<Span>>();

    static public SpanTable<Span> getCreateSpanTable(DbPlatform platform, String tableName) {

        SpanTable<Span> table = (SpanTable<Span>) getTable(platformList, platform, 
                getDefaultQuery(tableName));
        if(table == null) {
            table = new SpanTable<Span>(platform, tableName);
            getCreateTableList(platformList, platform).add(table);
        }
        return table;
    }

    private SpanTable(DbPlatform platform, String tableName) {
        super(platform, tableName);
    }
}

1 个答案:

答案 0 :(得分:1)

您可以使DbTable类中的工厂方法通用,以便它们保持通过平台列表传递给它们的特定表类型(T):

abstract public class DbTable<R extends DbRow> {  

    protected DbTable(DbPlatform platform, String tableName) {  }

    static class TableList<T extends DbTable<?>> extends ArrayList<T> {}

    static class PlatformTableList<T extends DbTable<?>> 
                    extends PairList<DbPlatform, TableList<T>> {}

    /** Return the matching DbTable with matching DbSelectStatement or null.
     * Will create/add a new TableList if platform not found. */

    static protected <T extends DbTable<?>> T getTable(PlatformTableList<T> platformList, 
            DbPlatform platform, DbSelectStatement stmt) {

        // Get the table from the list, or create new
        TableList<T> list = getCreateTableList(platformList, platform);
        // Search the list for a match
        for(T table : list) {
            if(table.equals(stmt))
                return table;
        }
        return null; 
    }

    /** Get or create and return a TableList for the Platform.  */
    static protected <T extends DbTable<?>> TableList<T> getCreateTableList(
            PlatformTableList<T> platformList, DbPlatform platform) { 

        TableList<T> list = platformList.getRightForLeft(platform);
        if(list == null) {
            list = new TableList<T>();
            platformList.addEntry(platform, list);            
        }
        return list;
    }

}

现在,您还可以使用getCreateSpanTable()方法删除广告

SpanTable<Span> table = getTable(platformList, platform, 
                getDefaultQuery(tableName));

正如评论中所指出的:如果你想在R课程中保留特定的行类型TableList,你可以写class TableList<R extends DbRow, T extends DbTable<R>> extends ArrayList<T> {}此外,我会尽量避免延长ArrayList {1}}并创建一个包含ArrayList的字段。