【问题标题】:Reducing if-else statements in Java减少 Java 中的 if-else 语句
【发布时间】:2012-05-11 17:58:46
【问题描述】:

我有以下代码:

void f(String t)
{
  if(t.equals("a"))
  {
    someObject.setType(ObjectType.TYPE_A);
  }
 else if(t.equals("b"))
  {
    someObject.setType(ObjectType.TYPE_B);
  }

// 50 more similar code

}

有没有什么简单的方法可以重写 if-else 条件,以免有那么多代码?

【问题讨论】:

    标签: java if-statement refactoring conditional-statements


    【解决方案1】:

    你应该使用一些东西来消除someObject.setType(ObjectType....)) 的重复如果ObjectTypeenum,那么在那里编写一个类似于valueOf 的方法来实现这一点。看看你是否喜欢这种解决方案:

    void f(String t) { someObject.setType(ObjectType.byName(t)); }
    
    enum ObjectType {
      TYPE_A, TYPE_B;
      public static ObjectType byName(String name) {
        return valueOf("TYPE_" + name.toUpperCase());
      }
    }
    

    【讨论】:

    • 不是吹毛求疵,你只需要小心这里的异常处理;您必须将返回值包装在 try-catch 块中,以处理垃圾输入场景。
    • @questzen 好吧,这只是基本大纲。根据愿望,有多种处理垃圾的方法。我个人通常更喜欢原始异常(如果传递垃圾确实是一个错误)。这为您提供了最直接的调试信息。
    【解决方案2】:

    使用从String 映射到ObjectType.TYPE_x 值的任何类型的Map(您必须填充)。

    【讨论】:

    • 是的,我也是这么想的。但我唯一怀疑的是存储这些字符串所需的内存以及获取类型所需的查找。没有别的办法吗?
    • @Asha 地图中的字符串(因为它们是被实习的)不会比字符串文字占用更多的空间。查找时间将减少,因为地图查找将是 O(log n) 而不是 O(n)
    • @Alnitak 使用HashMap 甚至可以访问O(1)
    • @Asha 如果您使用枚举,则不必显式管理地图。请参阅我的更新答案。
    • @Mudu 是的,这将是在这种情况下使用的一个很好的(具体)实现。
    【解决方案3】:

    我会将其添加为枚举的功能:

    public enum ObjectType {
        TYPE_A("a"),
        TYPE_B("b");
    
        private String stringType;
    
        private ObjectType(String stringType) {
            this.stringType = stringType;
        }
    
        public String getStringType() {
            return this.stringType;
        }
    
        public static ObjectType fromStringType(String s) {
            for (ObjectType type : ObjectType.values()) {
                if (type.stringType.equals(s)) {
                    return type;
                }
            }
            throw new IllegalArgumentException("No ObjectType with stringType " + s);
        }
    }
    
    ...
    
    void f(String t) {
        someObject.setType(ObjectType.fromStringType(t));
    }
    

    【讨论】:

    • 这是我常用的方法。比依赖常量名更好,因为它更灵活,更难破解。
    【解决方案4】:

    如果您可以将t 重构为char,则可以改用switch (Java 6):

    void f(char t) {
    
      switch(t) {
    
        case 'a`:
          someObject.setType(ObjectType.TYPE_A);
          break;
        case 'b':
          someObject.setType(ObjectType.TYPE_B);
          break;
    
        // ...
    
      }
    
    }
    

    正如 Marko 所指出的,您也可以在 Java 7 中使用 String

    它并没有那么短,但更优雅。此外,我认为它也可能更快,因为switch 与跳转表接近O(1)(有人可以确认这是否属实吗?),if 语句的数量是否为O(n)

    对于比单个setType 更复杂的实现,您可能还会想到State Pattern 实现。

    【讨论】:

      【解决方案5】:

      1.如果if条件数超过3个,可以选择switch语句。

      2.您可以将 if else 语句转换为ternary operations

      【讨论】:

        【解决方案6】:

        其他建议很棒——尤其是更智能的枚举和映射。但是我在这里要解决的第一个最基本的重构是提取一个方法来直接返回枚举,并让调用者只对该方法的返回值执行 setType。

        void f(String t) {
          final ObjectType type = findType(t);
          if (type != null)
            someObject.setType(type);
          }
        
        ObjectType findType(String t) {
          if (t.equals("a")) return ObjectType.TYPE_A;
          if (t.equals("b")) return ObjectType.TYPE_B;
          // 50 more similar code
          }
        

        在某些情况下,这本身就足够了;在其他情况下,findType() 方法可能会引导您使用基于映射或枚举的简单解决方案。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-20
          • 2023-03-28
          • 2011-11-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多