3

我是使用 Java Enums 的新手,我已经读过比较字符串文字的替换 IF 逻辑应该替换为 Enum。我不太明白如何用枚举替换下面的代码,有什么想法吗?基于传递给 applyEQ 的 col 值,我需要根据它的值执行下一个方法调用。我确实提前知道 col 的可能值,并且我现在正在使用常量文件。我应该创建一个枚举并将其放在我的常量接口文件中吗?

public class FilterHelper implements IFilterHelper {

   private final EQuery eQuery;

   public FilterHelper(EQuery query) {
      eQuery = query;
   }

    @Override
    public void applyEQ(String col, String val) throws Exception {
        int return = 0;
        if (col.equalsIgnoreCase(EConstants.NAME)) {
            ret = Sample.addName(eQuery, val);
        } else if (col.equalsIgnoreCase(EConstants.KEYWORDS)) {
            ret = Sample.addKey(eQuery, val);
        } else if (col.equalsIgnoreCase(EConstants.ROLE)) {
            ret = Sample.addRole(eQuery, val);
        }  

        if (return != 0) {
            throw new Exception("failed");
        }
    }
}

EConstants.java

public final class EConstants {    
    public static final String NAME = "cewName";
    public static final String KEYWORDS = "cewKeywords";
    public static final String ROLE = "cewRole";
}
4

7 回答 7

2

您可以将 EConstants 重写为枚举:

public enum EConstants {
  NAME, KEYWORDS, ROLE
}

并使用 switch 语句评估条件:

// col has type of EConstants
switch (col) {
  case NAME:
    // do something
    break;
  case KEYWORDS:
    // do something
    break;
  case ROLE:
    // do something
    break;
  default:
    // what to do otherwise
    break;
}
于 2012-04-05T15:43:17.833 回答
2

首先创建一个enum

public enum EConstants {
    CEWNAME,
    CEWROLE,
    CEWKEYWORDS;
}

然后将colString 转换为此enum并使用switch

public void applyEQ(String col, String val) throws Exception {
    int ret = 0;
    final EConstants constant = EConstants.valueOf(col.toUpperCase());
    switch(constant) {
        case CEWNAME:
            ret = Sample.addName(eQuery, val);
            break;
        case CEWROLE:
            ret = Sample.addRole(eQuery, val);
            break;
        case CEWKEYWORDS:
            ret = Sample.addKey(eQuery, val);
            break;
        default:
            throw new Exception("Unhandled enum constant: " + constant);
    }
}

请注意,如果不匹配任何常量值,EConstants.valueOf()则可以抛出。IllegalArgumentExceptioncol.toUpperCase()

顺便说一句,我讨厌在多个地方(和break关键字)初始化的局部变量,尝试提取方法:

final EConstants constant = EConstants.valueOf(col.toUpperCase());
final int ret = processSample(val, constant);

以及方法本身:

private int processSample(String val, EConstants constant) throws Exception {
    switch(constant) {
        case CEWNAME:
            return Sample.addName(eQuery, val);
        case CEWROLE:
            return Sample.addRole(eQuery, val);
        case CEWKEYWORDS:
            return Sample.addKey(eQuery, val);
        default:
            throw new Exception("Unhandled enum constant: " + constant);
    }
}
于 2012-04-05T15:47:59.020 回答
2

Java 枚举的伟大之处在于它们为类型安全枚举模式提供了语言级别的支持,因为它允许您定义方法甚至覆盖它们。所以你可以这样做:

public enum CewColumn {

NAME("cewName") {

    @Override
    public int add(EQuery eQuery, String val) {
        return Sample.addName(eQuery, val);
    }
}, 
KEYWORDS("cewKeywords") {

    @Override
    public int add(EQuery eQuery, String val) {
        return Sample.addKey(eQuery, val);
    }
}, 
ROLE("cewRole") {

    @Override
    public int add(EQuery eQuery, String val) {
        return Sample.addRole(eQuery, val);
    }
};

private final String colName;

private MyColumn(String colName) {
    this.colName = colName;
}

private static final Map<String, CewColumn> COLUMNS = new HashMap<>(values().length);
static{
    for (CewColumn cewColumn : values()){
        COLUMNS.put(cewColumn.colName, cewColumn);
    }
}

public abstract int add(EQuery eQuery, String val);

public static CewColumn getCewColumn(String colName){
    return COLUMNS.get(colName);
}
}

然后你可以像这样使用它:

CewColumn cewColumn = CewColumn.getCewColumn(colName);
if (cewColumn != null){
    int ret = cewColumn.add(eQuery, val);
}

-> 你用多态替换了 switch 语句!

于 2012-04-05T16:17:53.443 回答
1

最好创建一个枚举。

    public Enum AvailableCols{
       COL_1,
       COL_2;
    }

并将过程转换为

    public void applyEQ(AvailableCols col, String val) throws Exception { 
         switch(col){
             case COL1:
             ...

如果您仍然希望保留字符串,可以查看以下帖子

于 2012-04-05T15:54:39.237 回答
0

基本上创建一个枚举并更改类型col并使用equals()==比较col枚举值的值。或者,您可以使用switch语句,但我怀疑这会使您的代码仅对 3 个常量更具可读性。

例子:

enum EConstants {
   NAME,
   KEYWORDS,
   ROLE;
}

public void applyEQ(EConstants col, String val) throws Exception {
   if( col == EConstants.NAME ) {
    ...
   }
   ....
}

//or

public void applyEQ(EConstants col, String val) throws Exception {
   if( EConstants.NAME.equals(col) ) { //col might be null
    ...
   }
   ....
}

//or

public void applyEQ(EConstants col, String val) throws Exception {
   switch( col ) {
     case NAME: 
       ...
       break;
     case ROLE: 
       ...

   }

}
于 2012-04-05T15:43:59.763 回答
0

http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

如果您的原始数据是一个字符串,您仍然需要进行字符串比较来分配枚举。如果您对结果数据进行大量比较,这可能会更快,但如果没有,它只会增加代码的复杂性。

您可以像集合一样迭代枚举的值,这在您需要添加常量时为您提供了优势。这还不错。

这是如何做到的:

public enum EConstants {
    NAME, KEYWORDS, ROLE
}
...
public EConstants setConstant(String from) {
    if (from.equalsIgnoreCase("cewName")) {
        return NAME;
    } else if (col.equalsIgnoreCase("cewKeywords")) {
        return KEYWORDS;
    } else if (col.equalsIgnoreCase("cewRole")) {
        return ROLE;
    }      
}

您以这种方式预处理数据,现在当您试图找出逻辑时,您可以在枚举类型值上使用开关。

于 2012-04-05T15:49:25.090 回答
0

这是给你的一个窍门。不switch/case(只是想出一个更好的名字EConstants)。

public enum EConstants {
  NAME,
  KEYWORDS,
  ROLE;

  private interface Applier {
    void apply(EQuery query, String val);
  }

  public void apply(EQuery query, String val) {
    map.get(this).apply(query, val);
  }

  private static Map<EConstants, Applier> map = new HashMap<EConstants, EConstants.Applier>();
  static {
      map.put(NAME, new Applier() {

        @Override
        public void apply(EQuery query, String val) {
          Sample.addName(query, val);
        }

      });

      map.put(KEYWORDS, new Applier() {

        @Override
        public void apply(EQuery query, String val) {
          Sample.addKey(query, val);
        }

      });

      map.put(ROLE, new Applier() {

        @Override
        public void apply(EQuery query, String val) {
          Sample.addRole(query, val);
        }

      });
  }
}

现在你只需写:

@Override
public void applyEQ(EConstants econs, String val) {
    econs.apply(equery, val);
}
于 2012-04-05T16:02:21.490 回答