枚举的基本方法调用

时间:2012-04-05 18:31:12

标签: java methods enums invoke

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

3 个答案:

答案 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)代替你所拥有的循环来查找具有指定名称的该类型的枚举值,而不是像你正在做的那样循环。