我正在学习Java枚举,我想知道为了调用特定方法,检查多个枚举的匹配值的最佳方法是什么。我在下面定义了两个单独的枚举,这些枚举由getValue方法的colName参数用来确定要执行的方法。因此枚举驱动方法调用。必须有一种比我下面更有效的方法来做到这一点。有什么建议?
我想避免必须执行以下操作(伪代码):
if(colName.equalsIgnoreCase("ATTRIBUTEONE") ||
colName.equalsIgnoreCase("ATTRIBUTETWO") ||
colName.equalsIgnoreCase("ATTRIBUTETWO")){
callAsStringMethod();
} else if(colName.equalsIgnoreCase("ATTRIBUTEFOUR")){
callAsIntegerMethod();
}
我的尝试使用枚举:
public class RowHelper implements IRowHelper
public static enum StringAttributes {
ATTRIBUTEONE,
ATTRIBUTETWO,
ATTRIBUTETHREE;
}
public static enum IntegerAttributes {
ATTRIBUTEFOUR,
ATTRIBUTEFIVE,
ATTRIBUTESIX,
ATTRIBUTESEVEN;
}
@Override
public String getValue(String colName) throws Exception{
boolean colFound=false;
Object retValue = null;
for (EConstants.StringAttributes attribute : EConstants.StringAttributes.values()) {
if(colName.toUpperCase().equals(attribute)){
retValue = callAsStringMethod();
colFound=true;
}
}
for (EConstants.IntegerAttributes attribute : EConstants.IntegerAttributes.values()) {
if(colName.toUpperCase().equals(attribute)){
retValue = callAsIntegerMethod();
colFound=true;
}
}
if(!colFound)
throw new Exception("column not found");
if(retValue instanceof String )
return (String) retValue;
else
return retValue.toString();
}
}
答案 0 :(得分:1)
试试这个:
public String getValue(String colName) throws Exception {
final String name = colName != null ? colName.trim().toUpperCase() : "";
try {
EConstants.StringAttributes.valueOf(name);
return callAsStringMethod().toString();
} catch (Exception e1) {
try {
EConstants.IntegerAttributes.valueOf(name);
return callAsIntegerMethod().toString();
} catch (Exception e2) {
throw new Exception("column not found");
}
}
}
根据最新的问题编辑,该方法现在返回适当的值。
编辑:
根据Kirk Woll和Louis Wasserman的基准测试,循环values
明显快于try/catch
。所以这是原始代码的简化版本,期望它更快一点:
public String getValue(String colName) throws Exception {
final String name = colName != null ? colName.trim().toUpperCase() : "";
for (EConstants.StringAttributes attribute : EConstants.StringAttributes.values())
if (name.equals(attribute))
return callAsStringMethod().toString();
for (EConstants.IntegerAttributes attribute : EConstants.IntegerAttributes.values())
if (name.equals(attribute))
return callAsIntegerMethod().toString();
throw new Exception("column not found");
}
答案 1 :(得分:1)
嗯,这是一个奇怪的设计._。无论如何,你可以使用枚举,但我会喜欢:
public interface RowAttribute {
String getValue(IRowHelper rowHelper);
}
public class StringRowAttribute implements RowAttribute {
@Override
public String getValue(IRowHelper rowHelper) {
return rowHelper.callAsStringMethod();
}
}
public class IntegerRowAttribute implements RowAttribute {
@Override
public String getValue(IRowHelper rowHelper) {
return rowHelper.callAsIntegerMethod().toString();
}
}
public class RowHelper implements IRowHelper {
private static final RowAttribute INTEGER_ATTRIBUTE = new IntegerRowAttribute();
private static final RowAttribute STRING_ATTRIBUTE = new StringRowAttribute();
private static enum Attribute {
ATTRIBUTEONE(INTEGER_ATTRIBUTE),
ATTRIBUTETWO(INTEGER_ATTRIBUTE),
ATTRIBUTETHREE(INTEGER_ATTRIBUTE);
ATTRIBUTEFOUR(STRING_ATTRIBUTE),
ATTRIBUTEFIVE(STRING_ATTRIBUTE),
ATTRIBUTESIX(STRING_ATTRIBUTE),
ATTRIBUTESEVEN(STRING_ATTRIBUTE);
private final RowAttribute attribute;
private Attribute(RowAttribute attribute) {
this.attribute = attribute;
}
public RowAttribute getAttributeResolver() {
return this.attribute;
}
}
@Override
public String getValue(String colName) throws Exception {
final String name = colName != null ? colName.trim() : "";
for (Attribute attribute : Attribute.values()) {
if (attribute.name().equalsIgnoreCase(name)) {
return attribute.getAttributeResolver().getValue(this);
}
}
throw new Exception(String.format("Attribute for column %s not found", colName));
}
}
然后,您不需要创建多个枚举,并使用其功能来迭代可能的值。您只需要将方法callAsStringMethod / callAsIntegerMethod public。另一种方法是在RowHelper中插入实现。像这样:
public class RowHelper implements IRowHelper {
public interface RowAttribute {
String getValue();
}
private static final RowAttribute INTEGER_ATTRIBUTE = new RowAttribute() {
@Override
public String getValue() {
return callAsIntegerMethod().toString();
}
};
private static final RowAttribute STRING_ATTRIBUTE = new RowAttribute() {
@Override
public String getValue() {
return callAsStringMethod();
}
};
...
@Override
public String getValue(String colName) throws Exception {
...
if (attribute.name().equalsIgnoreCase(name)) {
return attribute.getAttributeResolver().getValue();
}
...
}
}
无论如何,我不明白你的方法如何在不将colName作为参数传递给它的情况下获得属性值。
答案 2 :(得分:0)
坦率地说,使用多个枚举执行此操作的最有效方法是使它们成为相同的枚举。没有更好的方法。
那就是说,你可以使用Enum.valueOf(EnumClass.class, name)
代替你所拥有的循环来查找具有指定名称的该类型的枚举值,而不是像你正在做的那样循环。