【问题标题】:Multiple if statements having incorrect output [duplicate]多个 if 语句的输出不正确[重复]
【发布时间】:2016-11-27 07:06:50
【问题描述】:

我想用一些枚举值填充acts 数组。迭代时我想从控制台输入命令,但我的 if 语句找不到任何匹配项,我总是得到输出 "Incorrect"

我的代码:

Action[] acts = new Action[n];
for(int i = 0; i < n; i++) {
    System.out.println("Enter act: ");
    Scanner in1 = new Scanner(System.in);
    String s = in1.next();
    acts[i] = new Action();
    if (s.equals("rotate_forw")) 
        acts[i].type = ActionType.RotF;
    if (s.equals("rotate_back")) 
        acts[i].type = ActionType.RotB;
    if (s.equals("shift_forw")) 
        acts[i].type = ActionType.ShiftF;
    if (s.equals("shift_back")) 
        acts[i].type = ActionType.ShiftB;
    else 
        System.out.println("Incorrect");
}

【问题讨论】:

  • 你描述了你想要什么,但没有描述你面临什么问题。您是否收到任何错误/异常/不正确的结果?

标签: java arrays enums


【解决方案1】:

您的else 子句仅适用于最后一个if 语句,因此只要s.equals("shift_back")false,您就会得到"Incorrect" 输出。

您的语句应替换为单个 if-else-if...-else 语句,以便仅在 所有条件为 false 时打印"Incorrect"

Action[] acts = new Action[n];
for(int i = 0; i < n; i++) {
    if (s.equals("rotate_forw"))
        acts[i].type = ActionType.RotF;
    else if (s.equals("rotate_back"))
        acts[i].type = ActionType.RotB;
    else if (s.equals("shift_forw"))
        acts[i].type = ActionType.ShiftF;
    else if (s.equals("shift_back"))
        acts[i].type = ActionType.ShiftB;
    else
        System.out.println("Incorrect");
}

当输入不正确时,您还应该考虑要分配给acts[i].type 的内容。在这种情况下,也许你应该抛出一个异常。

【讨论】:

    【解决方案2】:

    虽然@Eran 的回答是正确的,但我想提出一种不同的方法,将枚举与外部编码的翻译一起封装起来。考虑一下:

    public class EnumDemo
    {
        public static enum ActionType
        {
            Incorrect(""),
            RotF("rotate_forw"),
            RotB("rotate_back"),
            ShiftF("shift_forw"),
            ShiftB("shift_back");
    
            private String code;
            private ActionType(String code)
            {
                this.code = code;
            }
    
            public static ActionType fromString(String code)
            {
                return Arrays.stream(ActionType.values())
                             .filter(v->v.code.equals(code))  
                             .findFirst()
                             .orElse(ActionType.Incorrect);
            }
        }
    
        public static void main(String[] args)
        {
            String[] testData = {  
                "rotate_forw", 
                "rotate_back", 
                "shift_forw", 
                "shift_back", 
                "junk", 
                null };
    
            Arrays.stream(testData)
                  .forEach(t->System.out.printf("\"%s\" -> ActionType.%s\n", t, ActionType.fromString(t)));
        }
    }
    

    这使用了枚举常量可以具有关联数据的事实。我添加了一个实例变量code 来保存每个枚举值的外部编码。然后我在枚举中添加了一个静态fromString(String code) 方法,用于在值列表中查找提供的代码。对于 4 种可能性,一个简单的线性搜索,相当于您的 if-then-else 级联,工作正常。如果有几十个或更多,我会设置一个Map&lt;String,ActionType&gt; 来处理转换。

    使用流的搜索有一些解释。

    1. 首先创建一个枚举值的Stream
    2. 过滤它以仅包含 code 与所需代码匹配的枚举值(应该只有一个)
    3. 选择第一个条目,它以Optional 返回。如果未找到任何内容(即代码无效),Optional 将为空。
    4. 如果值存在则使用orElse 方法返回值,如果不存在则使用ActionType.Incorrect

    乍一看,这可能看起来效率低下,因为人们预计 filter() 谓词必须扫描整个流,即使所需的元素出现得早。这是 Streams 的一个非常棒的特性——所有中间流都是“惰性的”,所以如果过滤器尽早找到所需的条目,它就不会遍历整个列表。详情请见this question

    输出:

    "rotate_forw" -> ActionType.RotF
    "rotate_back" -> ActionType.RotB
    "shift_forw" -> ActionType.ShiftF
    "shift_back" -> ActionType.ShiftB
    "junk" -> ActionType.Incorrect
    "null" -> ActionType.Incorrect
    

    最后一个测试用例显示代码是空安全的。

    最大的优点是映射与枚举本身位于同一位置,因此您在添加或删除枚举值时不必寻找代码。你也不能忘记定义映射,因为它是枚举的构造函数所需要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      • 2018-09-21
      • 1970-01-01
      • 1970-01-01
      • 2016-03-20
      • 1970-01-01
      相关资源
      最近更新 更多