gpt4 book ai didi

java - 如何使用静态成员泛化 Java 枚举?

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

我正在重构旧应用程序的一部分,该应用程序处理从 Excel 工作表导出和导入数据库表。我们为每个表都有一个 Formatter 子类,用于提供该表的定义:它有多少列,以及每列的名称、格式和 validator 是什么。然后,导出/导入表的模板方法将调用提供此数据的 getter。我已将列数据提取到枚举中,这大大简化了代码。格式化程序现在看起来像这样(为简洁起见,省略了一些细节):

public class DamageChargeFormatter extends BaseFormatter {
public static final int NUM_COLUMNS = 7;

public enum Column {
VEHICLE_GROUP(0, "Vehicle Group", /* more params */),
NAME_OF_PART(1, "Name of Part", /* more params */),
//...
LOSS_OF_USE(6, "Loss of Use", /* more params */);

private static final Map<Integer, Column> intToColumn = new HashMap<Integer, Column>();

static {
for (Column type : values()) {
intToColumn.put(type.getIndex(), type);
}
}

public static TableColumn valueOf(int index) {
return intToColumn.get(index);
}

private int index;
private String name;

Column(int index, String name, /* more params */) {
this.index = index;
this.name = name;
//...
}

public int getIndex() { return index; }

public String getName() { return name; }

// more members and getters...
}

protected String getSheetName() {
return "Damage Charges";
}

public String getColumnName(int columnNumber) {
TableColumn column = Column.valueOf(columnNumber);

if (column != null) {
return column.getName();
}
return null;
}

// more getters...

protected int getNumColumns() {
return NUM_COLUMNS;
}

protected boolean isVariableColumnCount() {
return false;
}
}

现在,我有大约十几个这样的类,每个类都包含完全相同的代码,只是 NUM_COLUMNSColumn 的枚举值不同。有没有办法以某种方式通用化这个?这样做的主要障碍是静态 Column.valueOf() 方法和静态常量 NUM_COLUMNS。后者的另一个问题是它确实属于更高一级的抽象,即表,而不是单个列 - 如果能以某种方式将其合并到通用解决方案中会很好。

从技术上讲,我可以使用基本接口(interface)(下面的TableColumn)和反射来解决这个问题,但我真的不喜欢这样,因为除了将编译时错误换成运行时错误之外,它还使代码变得丑陋(对我来说):

public class GenericFormatter<E extends TableColumn> extends BaseFormatter {
private Method valueOfMethod;

public GenericFormatter(Class<E> columnClass) {
try {
valueOfMethod = columnClass.getDeclaredMethod("valueOf", Integer.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}

public String getColumnName(int columnNumber) {
try {
@SuppressWarnings("unchecked")
E elem = (E) valueOfMethod.invoke(columnNumber);

if (elem != null) {
return elem.getName();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}

//...
}

请注意,此代码纯粹是实验性的,尚未经过测试...

有没有更好、更干净、更安全的方法?

最佳答案

可能是这样的:

public class TableMetadata<E extends Enum & TableColumn> {
private Map<Integer, TableColumn> columns = new HashMap<Integer, TableColumn>();

public TableMetadata(Class<E> c) {
for (E e: c.getEnumConstants()) {
columns.put(e.getIndex(), e);
}
}

public String getColumnName(int index) {
return columns.get(index).getName();
}
}

public class GenericFormatter<E extends TableColumn> extends BaseFormatter {
private TableMetadata<E> m;

public GenericFormatter(TableMetadata<E> m) {
this.m = m;
}

public String getColumnName(int columnNumber) {
return m.getColumnName(index);
}

//...
}

编辑: Enum 添加到类型参数以提高编译时安全性

关于java - 如何使用静态成员泛化 Java 枚举?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2419123/

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