我已经用Java编程好几年了,但我最近才回到学校获得一个正式学位。我很惊讶地发现,在我的上一个作业中,我因为使用下面这样的循环而失分。

do{
     //get some input.
     //if the input meets my conditions, break;
     //Otherwise ask again.
} while(true)

现在对于我的测试,我只是扫描一些控制台输入,但我被告知这种循环是不鼓励的,因为使用break类似于goto,我们只是不这样做。

我完全理解goto和它的Java兄弟break:label的陷阱,而且我很明智地不使用它们。我也意识到,一个更完整的程序会提供一些其他的逃避方式,比如结束程序,但我的教授并没有提到这一点,所以……

do-while(正确)怎么了?


当前回答

我认为这确实很糟糕……或者至少对许多开发人员来说是这样。这是开发人员不考虑循环条件的症状。因此很容易出错。

其他回答

1) do -while没有错(正确)

2)你的老师错了。

NSFS ! !:

3)大多数老师是老师而不是程序员。

我不会说这很糟糕——但同样地,我通常至少会寻找另一种选择。

如果这是我写的第一件事,我几乎总是至少试着把它重构成更清晰的东西。有时这是没有办法的(或者另一种选择是使用bool变量,它除了指示循环的结束之外没有任何意义,比break语句更不清楚),但至少值得一试。

作为一个使用break比使用flag更清楚的例子,考虑:

while (true)
{
    doStuffNeededAtStartOfLoop();
    int input = getSomeInput();
    if (testCondition(input))
    {
        break;
    }
    actOnInput(input);
}

现在让我们强制它使用一个标志:

boolean running = true;
while (running)
{
    doStuffNeededAtStartOfLoop();
    int input = getSomeInput();
    if (testCondition(input))
    {
        running = false;
    }
    else
    {
        actOnInput(input);
    }
}

我认为后者读起来更复杂:它有一个额外的else块,actOnInput更缩进,如果您试图弄清楚当testCondition返回true时发生了什么,您需要仔细检查块的其余部分,以检查else块之后是否有什么东西会发生,无论running是否被设置为false。

break语句更清楚地传达了意图,并让块的其余部分继续做它需要做的事情,而不必担心前面的条件。

请注意,这与人们对方法中多个return语句的争论完全相同。例如,如果我可以在前几行内计算出一个方法的结果(例如,因为一些输入是空的,或者是空的,或者是零),我发现直接返回答案比用一个变量来存储结果,然后是一整个代码块,最后是一个返回语句更清楚。

也许是我运气不好。或许我只是缺乏经验。但是每次我回忆起处理while(true)内部有break时,可以改进将Extract Method应用到while-block的代码,它保留了while(true),但(巧合吗?)将所有的break转换为返回。

根据我的经验,没有休息(即返回或抛出)是相当舒服和容易理解的。


  void handleInput() {
      while (true) {
          final Input input = getSomeInput();
          if (input == null) {
              throw new BadInputException("can't handle null input");
          }
          if (input.isPoisonPill()) {
              return;
          }
          doSomething(input);
      }
  }

根据我的经验,在大多数情况下循环有“主要”条件继续。这是应该写入while()操作符本身的条件。所有其他可能打破循环的条件都是次要的,不那么重要。它们可以被写成额外的if() {break}语句。

而(正确)往往令人困惑,可读性较差。

我认为这些规则并不能覆盖100%的情况,而可能只有98%。

我想说,一般来说,它不被认为是一个好主意的原因是你没有充分发挥这个结构的潜力。此外,我倾向于认为许多编程教师不喜欢他们的学生带着“包袱”进来。我的意思是,我认为他们喜欢成为学生编程风格的主要影响因素。也许这只是老师的一个讨厌的地方。