3

我正在学习 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();
            }
        }
4

3 回答 3

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");

}
于 2012-04-05T18:38:22.313 回答
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 公开。另一种方法是在 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 作为参数传递给它的情况下真正获得属性值的。

于 2012-04-05T20:06:31.777 回答
0

坦率地说,使用多个枚举执行此操作的最有效方法是使它们成为相同的枚举。真的没有更好的办法了。

也就是说,您可以使用Enum.valueOf(EnumClass.class, name)指定名称来查找该类型的枚举值,而不是您拥有的循环,而不是像您正在做的那样循环。

于 2012-04-05T18:32:28.373 回答