3

私はJava列挙型について学んでおり、特定のメソッドを呼び出すために、一致する値について複数の列挙型をチェックするための最良のアプローチは何であるか疑問に思いました。実行するメソッドを決定するためにgetValueメソッドのcolNameパラメーターによって使用される2つの別々の列挙型を以下に定義しました。したがって、列挙型はメソッド呼び出しを駆動します。これを行うには、以下の方法よりも効率的な方法が必要です。助言がありますか?

以下を実行する必要はありません(擬似コード):

 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 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をパブリックにするだけで済みます。もう1つの方法は、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 に答える
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 に答える
0

複数の列挙型でこれを行う最も効率的な方法は、率直に言って、それらを同じ列挙型にすることです。本当に良い方法はありません。

とは言うものの、ループの代わりに、あなたがしているEnum.valueOf(EnumClass.class, name)ようにループするのではなく、指定された名前でそのタイプの列挙値を見つけるために使用することができます。

于 2012-04-05T18:32:28.373 に答える