以下是一个清理示例,可将其简化为一个问题。有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;
}
}
跨度表:
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);
}
}
最佳答案
您可以使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
并创建一个包含ArrayList
代替。