以下是一个经过清理的示例,可将其简化为单个问题。有 3 个类文件(里面有一些类外壳)。不起作用的是 SpanTable
类中每个 getTable()
和 getCreateTableList()
的第一个参数转换。我想知道如何让该参数具有其原始 Span/SpanTable
子类类型并传递到 DbTable
调用中?或者实际上,DbTable 不需要额外的信息,但我希望 SpanTable 或任何调用者保留其类型。
数据库行:
public class DbRow {
static class Span extends DbRow {}
}
数据库表:
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
的字段相反。
关于在子类化(和静态方法)中使用泛型的 Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42353140/