gpt4 book ai didi

java - 使用枚举值的成员类型声明泛型类时遇到问题

转载 作者:太空宇宙 更新时间:2023-11-04 14:55:05 25 4
gpt4 key购买 nike

我试图以一种使用类型的方式声明一个泛型类,该类型可能会发生变化,而不必在每次类型更改时重构我的泛型类。就像,如果成员(member) a枚举值 AString ,然后声明 Example<a>与声明 Example<String> 一样好.

但是,我在声明它时遇到了麻烦,因为我似乎无法解决我想要对类型执行的操作。我将尝试提供我的详细信息的简化示例,然后我将能够更详细地描述问题。

代码示例

这个enum声明表中列的类型。 (它基本上是从 SQL 数据类型到 Java 数据类型的映射。)

public enum ColTypes {
VARCHAR( String.class ),
INTEGER( Integer.class );

public final Class<?> dataType;
public ColTypes (Class<?> dataType) {
this.dataType = dataType;
}
}

这个接口(interface)代表一个列本身。

public interface Column<T> {
public Object getColVal(T t);
}

下面是表示某个表中的行的类的示例。然而,我有许多不同类型的这些类,所以我实际上设置了一些脚本来根据数据库模式生成此代码。它们本质上是愚蠢的数据对象,可能比这更复杂一点......

为了让此类的客户端在表中为该类的对象指定一列,我添加了 enumColumn就在里面。这样,您可以使用Column类的内部枚举作为参数,这样你就可以 getColVal()一般而言,不需要指定特定的 getter。看:

public class DBRow {
private String foo;
private Integer bar;
public DBRow(String foo, Integer bar) {
this.foo = foo;
this.bar = bar;
}
public String getFoo() {
return this.foo;
}
public Integer getBar() {
return this.bar;
}

public enum DBCols implements Column<DBRow> {
FOO( ColTypes.VARCHAR ) {
public Object getColVal(DBRow r) {
return r.getFoo();
}
},
BAR( ColTypes.INTEGER ) {
public Object getColVal(DBRow r) {
return r.getBar();
}
};

public final ColType colType;
public DBCols(ColType colType) {
this.colType = colType;
}
}
}

所以你可以假设,对于某些人 DBRow row ,调用DBRow.FOO.getValue(row)而不是做row.getFoo() 。对于传递 DBRow.FOO 很有用或DBRow.BAR作为一个论据!

这个类是我所拥有的类的一个非常简化的版本,它通过使用这种策略来处理数据库对象的集合。

public abstract class ColValsGetter<T> {
protected List<T> objs;
protected Column<T> col;
protected ColValsGetter(List<T> objs, Column<T> col) {
this.objs = objs;
this.col = col;
}
protected Object getColValForObj(int index) {
return col.getColVal(objs.get(index));
}
}

这是一个简单的示例,说明如何在具体类中使用它。我想要一个 BAR列也。我没有使这些类通用的原因是,处理每一列的逻辑对于该列来说是非常特殊的,因此很难抽象出大部分行为,以便我可以使这些 ColValsGetter采取Column他们正在使用的类型作为类型参数。

public class DBRowFooColValsGetter extends ColValsGetter<DBRow> {
private String fooVal;
public DBRowFooColValsGetter(List<DBRow> rows) {
super(rows, DBRow.DBCols.FOO);
}
public void complexLogicForFooOnly(int i) {
fooVal = (String) getColValForObj(i);
// do a lot of stuff that only makes sense for the FOO column
};
}

问题

现在,我的问题是架构中类型的潜在更改。 (我知道,听起来很可疑,但请忽略它。)强制转换为 String我这样做会导致ClassCastException如果FOO列更改为 INTEGER类型。我更愿意声明ColValsGetter<T, E>并让它getColValForObj(int)方法返回 E 。但是,将其声明为类似 ColValsGetter<DBRow, String>不好,因为它也遇到同样的问题。我想声明的是:

public class DBRowFooColValsGetter extends
ColValsGetter<DBRow, DBRow.DBCols.FOO.colType.dataType>

这样,如果架构发生变化,类将自动调整。 (请相信我,尽管我无法抽象这些 ColValsGetter 的行为以使它们对列通用,但我可以抽象数据类型。)

但是,我的尝试失败了。 Eclipse 说 DBRow.DBCols.FOO无法解析为类型。我想我明白为什么,因为 dataTypeClass对象,但是当我添加 .class 时最后我得到一个语法错误(“需要标识符。”)我不应该能够在编译时从枚举值中获取我想要的类型吗?

我真的很希望能够以某种方式完成此行为。有任何想法吗?或者这不可能吗?

最佳答案

我认为您希望能够更改枚举并使其他所有内容保持可编译。

这几乎是不可能的,因为类型在 Java 中并不是真正的一流数据。您的客户端代码需要使用强类型对象,并且您无法在运行时从异构枚举或任何其他异构数据结构中获取该对象。

您可以在枚举中包含这些 getter(如函数对象),并使用委托(delegate)来嵌入业务逻辑,但最终仍会进行强制转换。

public class ColValsGetter<T> {
protected List<T> objs;
protected Column<T> col;
public ColValsGetter(List<T> objs, Column<T> col) {
this.objs = objs;
this.col = col;
}
public T getColValForObj(int index) {
return col.getColVal(objs.get(index));
}
}
public class ColValsGetterFactory< T > {
public ColValsGetterFactory() {}
public ColValsGetter< T > make( List< T > lt, Column< T > col ) {
return new ColValsGetter< T >( lt, col );
}
}
public enum ColTypes {
VARCHAR( String.class, new ColValsGetterFactory< String >() ),
INTEGER( Integer.class, new ColValsGetterFactory< Integer >() );

public final Class<?> dataType;
public final ColValsGetterFactory< ? > gf;
public < T > ColTypes ( Class< T > dataType, ColValsGetterFactory< T > gf ) {
this.dataType = dataType;
this.gf = gf;
}
}

public class DBRowFooColValsGetter {
private String fooVal;
private ColValsGetter< String > getter;
public DBRowFooColValsGetter( List< DBRow > rows ) {
this.getter = ( ColValsGetter< String > )DBRow.DBCols.FOO.colType.gf.make( rows, DBRow.DBCols.FOO );
}
public void complexLogicForFooOnly( int i ) {
fooVal = getter.getColValForObj( i );
// do a lot of stuff that only makes sense for the FOO column
};
}

关于java - 使用枚举值的成员类型声明泛型类时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23302335/

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