IntelliJ抱怨“for语句不循环”?

时间:2016-03-30 08:53:18

标签: java for-loop intellij-idea

这是我的代码:

public enum Modification {
    NONE, SET, REMOVE;
}

boolean foo(){
    for (S s : sList) {
        final Modification modification = s.getModification();
        switch (modification) {
            case SET:
            case REMOVE:
                return true;
            /*
            case NONE:
                break;
            */
        }
    }
    return false;
}

当代码如上所示时,IntelliJ会说:

  

'for'语句不会循环更少...()报告for的任何实例,   while和do语句保证最多执行   一旦。通常情况下,这表示存在错误。

只有我做出以下更改,IntelliJ才会高兴:

for (S s : sList) {
    final Modification modification = s.getModification();
    switch (modification) {
        case SET:
        case REMOVE:
            return true;
        case NONE:
            break;
    }
}

如果 case NONE:未包含在switch语句中,为什么我的for循环不循环?

5 个答案:

答案 0 :(得分:7)

我刚刚在eclipse中试过这个,你最终会在switch语句中发出编译器警告。

  

枚举常量NONE在修改

上的枚举开关中需要相应的案例标签

要解决警告,我会给出以下选项。

  • 添加默认案例
  • 添加遗失案例陈述
  • 将@SuppressWarnings'incomplete-switch'添加到foo()

如果我添加了缺失的case语句,则警告不再出现。与添加缺失的案例相同,使您的错误警告从intellij消失。

如果没有case NONE的语句,你只能看到两种情况,两种情况都返回true。在不知道修改的结构和NONE的额外值的情况下,看起来这个循环只会在循环的第一次迭代时返回true。

当然编译器应该知道修改的值多于SET和REMOVE,所以警告只是为了好的风格。基本上你的代码可以工作,但是这里是如何改进它。

我会选择添加默认语句而不是丢失的案例。如果稍后将更多值添加到枚举中,这将是更具前瞻性的证据。 E.G。

switch (modification) 
{
  case SET:
  case REMOVE:
    return true;
  default:
    break;
}

就我个人而言,我不喜欢在switch语句中使用fall-through。你在使代码简洁的过程中获得了什么,你在可读性方面失去了恕我直言。如果有人后来在SET和REMOVE之间添加一个案例,它可能会引入一个错误。此外,通过方法中途返回语句也可能导致问题。如果有人想在返回之前添加一些代码,他们可能会错过所有的地方。如果方法非常简单,那么多次返回就没问题,但你已经说过这是一个简化的例子,所以如果这段代码很复杂,我会避免它。

如果您能够使用Java 8,那么这看起来是新流API的完美用例。以下内容应该有效。

return sList.stream().anyMatch(
  modification -> (modification==Modification.SET || modification==Modification.REMOVE)
);

答案 1 :(得分:2)

我认为这是你唯一的三种情况吗?所以基本上它说你要打前两个中的一个然后立即返回true,因此不循环,只需添加一个default案例,一切都应该有效好的,这也是很好的做法。

基本上它无法看到它不会立即返回而不迭代循环的情况

答案 2 :(得分:2)

我说它是误报。

第一个迹象: 如果您通过调试器运行代码 - 并且在具有其他修改的元素之前在列表中包含NONE修改的元素 - 它将实际循环。

第二个指示: 当你查看生成的字节码时,它会将switch语句转换为(排序 - 它不是完全相同)

for (S s : sList) {
    Modification modification = s.getModification();
        switch (modification.ordinal()) {
            case 1:
            case 2:
                return true;
    }
}

如果你把它放在你的代码中,IntelliJ不会抱怨。

第3个指示: 如果您在返回之前添加了一个附加声明,即System.out.println();

,警告就会消失
 switch (modification) {
     case SET:
     case REMOVE:
       System.out.println()
       return true;

似乎你用缺少的案例标签欺骗了检查,并且可以简单地忽略警告。

答案 3 :(得分:1)

我认为IntelliJ的检查是错误的。我向JetBrains

报告了这个问题

编辑:已修复

答案 4 :(得分:0)

您的开关盒总是断裂或返回。在第一种情况下,你什么也不做,falls through。第二种情况return导致开关和循环停止。在第三种情况下,你break导致它停止的switch语句。然而,它不会停止for循环(也就是说,它会继续迭代)。

SET案例添加特定功能,或在REMOVENONE案例中更改您的行为。

public enum Modification {
    NONE, SET, REMOVE;
}

boolean foo(){
    for (S s : sList) {
        final Modification modification = s.getModification();
        switch (modification) {
            case SET:
               // This case falls through to the REMOVE case
            case REMOVE:
                return true; // This statement stops the switch, loop and returns true
            case NONE:
                break; // This statement stops the switch and continues the loop.
        }
    }
    return false;
}

如果没有NONE情况,您的交换机不会循环,因为return会中断循环并从函数返回一个值。 break打破了切换循环,但继续for循环。

根据OP的要求提供额外的解释。

下降意味着下一个案例将被执行,直到达到停止(breakreturn)。这使得以下代码片段等效:

case SET:
case REMOVE:
    return true;

与:

相同
case SET:
    return true;
case REMOVE:
    return true;