Calling the base method for enumeration

I am looking into Java enums and I was curious to know what is the best for checking multiple enums for the corresponding value in order to call a particular method. I've defined two separate enums below, which are used by the getNalue parameter of the colName method to determine which method to execute. Thus, the enumeration controls the method invocation. There must be a more efficient way to do this than what I have. Any suggestions?

I want to avoid having to do below (pseudocode):

 if(colName.equalsIgnoreCase("ATTRIBUTEONE") || 
       colName.equalsIgnoreCase("ATTRIBUTETWO") || 
          colName.equalsIgnoreCase("ATTRIBUTETWO")){
             callAsStringMethod();
    } else if(colName.equalsIgnoreCase("ATTRIBUTEFOUR")){
         callAsIntegerMethod();
    }

      

My attempt using an enum:

 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


source to share


3 answers


Try the following:

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

}

      

The method now returns the appropriate value according to the last change to the question.



EDIT:

According to the criterion of Kirk Wall and Louis Wasserman, going through values

is significantly faster than doing it try/catch

. So here's a simplified version of the source code, expect it to be slightly faster:

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


source


Well, that's a weird design. Anyway, you can use an enum, but I would like:

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

      

Then you don't have to create more than one enum and use its strength to iterate over possible values. You only need to make the callAsStringMethod / callAsIntegerMethod methods public. Another way is to inject the implementations inside the RowHelper. Something like that:



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();
        }
        ...
    }

      

}

Anyway, I don't understand in your method how you actually get the value of the attribute without passing the colName parameter to it.

+1


source


The most efficient way to do this with multiple enums is, frankly, to make them the same enumeration. There really is no better way.

However, instead of having a loop, you can use Enum.valueOf(EnumClass.class, name)

to find an enumeration value of that type with the specified name, rather than a loop as you do.

0


source







All Articles