gpt4 book ai didi

Java:如何从

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:22:30 25 4
gpt4 key购买 nike

我有一个 enum存储数据库表的一些元数据:

static enum DataTable implements TableMetaData {

HISTORIES ("h", Hx.class, HxColumn.HPI_ID),
:
:

private final String e_alias;
private final Class<? extends Row> e_tbl;
private final ColumnMetaData e_idCol;

DataTable(String al,
Class <? extends Row> c1,
ColumnMetaData id)
{...}

@Override public Class<? extends Row> modelClass() { return this.e_tbl; }
:
:
}

感兴趣的领域是e_tbl其中存放的是数据库表对应的模型对象类。该项目中的所有模型对象类都实现了一个 Row界面。我希望能够访问此字段以生成此类的实例。

我的问题是,我使用的是未经检查的转换,我不知道它是否安全,而且我无法弄清楚如何执行运行时检查以确保模型对象匹配。这是发生转换的代码:

static final <E extends Row> List<E> doQuery (
final List<JdbcValue> pars,
final String sql,
final TableMetaData dm
)
{

List<E> result = new ArrayList<E>();

@SuppressWarnings("unchecked")
Class<E> cls = (Class<E>) dm.modelClass();
:
:
}

我认为这是一个危险的转换。该查询旨在生成 E实例,这些实例将使用提供的枚举常量中包含的模型类创建。问题是我不知道 E匹配枚举中存储的类标记。这是一种情况 Class.asSubclass()似乎无法帮助我。

问题是我有一个字段是 <? extends Row>我需要让它与 <E extends Row> 兼容.

一个解决方案是将方法重构为它需要 Class<E> cls参数而不是枚举。这将至少提供一些编译时保证,即类标记适合正在生成的结果列表的类型。但是,这仍然不能使我使用枚举中的数据;我仍然必须在方法调用之前对其进行转换。

我可以使用支票吗?

============================================= ===

2014 年 12 月 6 日更新

在我看来,这是一个没有好的、干净的解决方案的问题。

枚举不支持泛型类型参数(它们不能)。

每次您尝试将参数化类型存储在枚举常量中时,都会在编译时出现不兼容的类型信息。

如建议的那样,使用参数化的类型安全单例模式将使编译器能够检查类型安全,但我拥有的 API 被这些枚举类所渗透,我不认为我可以将它们重构为常规类。

为了限制损失,我想知道以下推理是否准确:

  • 与枚举常量关联的数据是静态的和最终的;在这里它也是不可变的。

  • 我完全控制进入枚举常量的数据,所以我知道在运行时 e_tbl字段将始终是 Class扩展 Row 的某种类型的对象.

这些假设承认两种我认为具有相同缺陷的方法。在枚举类中,访问器方法被重写为:

@Override public <E extends Row> Class<E> modelclass() { 
@SuppressWarning("unchecked")
Class<E> cls = (Class<E>) this.e_tbl;
return this.e_tbl; }
  1. 我可以将枚举数据存储到使用原始类型的字段中。原始类型与通用访问器方法互操作,因此它可以编译,但会生成警告。

  2. 我可以将枚举数据存储到使用 <? extends Row> 的字段中通配符类型。这不会使用通用访问器方法 ( <E> extends Row> ) 进行编译,因此我必须使用未经检查的强制转换。仍然会生成警告。

因为我知道枚举数据总是扩展 Row ,我认为这可能是可以的。我不能做的是保证正在检索的枚举数据适用于 List正在生成的类型。但我认为除了记录 API 用户必须为返回的查询发送正确的 TableMetaData 常量,否则结果将是“未定义的”之外,没有任何方法可以控制这一点。

由于枚举不适用于泛型类型,我认为没有更好的解决方案。

最佳答案

你可以做的一件事:

  • TableMetaData进入TableMetaData<E>并根据 E 定义类
  • 去掉 enum (因为它们不支持类型参数)并编写一个类每个枚举条目

所以界面大概是这样的

class Histories implements TableMetaData<SpecialRowType> {
Class<SpecialRowType> modelClass();
}

最终应该允许您cast使用它。

static final <E extends Row> List<E> doQuery (
final List<JdbcValue> pars,
final String sql,
final TableMetaData<E> dm
)
{

List<E> result = new ArrayList<E>();
// type safe, because E refers to the same thing.
Class<E> cls = dm.modelClass();
:
}

现在编译器可以确定 ? extends Row类与 E extends Row 相同类,它们确实有一个共同的祖先,但这并不意味着您可以将它们相互转换。

关于Java:如何从 <?扩展 ...> 到 <E>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27256518/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com