Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 是";while(true)“;那么糟糕?_Java_While Loop_Do While - Fatal编程技术网

Java 是";while(true)“;那么糟糕?

Java 是";while(true)“;那么糟糕?,java,while-loop,do-while,Java,While Loop,Do While,我已经用Java编程好几年了,但我最近刚回到学校获得正式学位。我很惊讶地发现,在我的上一次作业中,我因为使用下面的循环而丢了分数 do{ //get some input. //if the input meets my conditions, break; //Otherwise ask again. } while(true) 现在,对于我的测试,我只是在扫描一些控制台输入,但是我被告知不鼓励这种循环,因为使用break类似于goto,我们只是不这样做 我完全

我已经用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(true)
有什么问题?

我不会说这不好,但同样地,我通常至少会寻找一个替代方案

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

作为一个使用
break
比使用标志更清晰的示例,请考虑:

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
块,
actioninput
更缩进,如果您试图计算出
testCondition
返回
true
时会发生什么,您需要仔细查看块的其余部分,以检查
else
块之后是否有任何内容,无论
running
是否设置为
false
,都不会出现这种情况

break
语句更清楚地传达了意图,并让块的其余部分开始它需要做的事情,而不必担心早期的条件


请注意,这与人们对一个方法中的多个返回语句所持的论点完全相同。例如,如果我能在前几行内计算出某个方法的结果(例如,因为某些输入为null、空或零),我会发现直接返回该答案比使用变量存储结果更清晰,然后是一整段其他代码,最后是一个
return
语句。

您可以使用一个布尔标志来指示何时结束while循环<代码>中断和
转到
是软件难以维护的原因-软件危机(tm)-应该避免,也很容易避免

这是一个你是否务实的问题。在这种简单的情况下,实用主义的程序员可能只是使用break


但最好养成不使用它们的习惯,否则你可能会在不合适的情况下使用它们,比如在复杂的嵌套循环中,使用
break
会使代码的可读性和可维护性变得更加困难,这更像是一种美学上的东西,更易于阅读的代码,其中明确知道循环将在循环声明中停止的原因

什么都没有,真的。老师们只是对goto过敏,因为他们在某个地方听说它真的很糟糕。否则你只会写:

bool guard = true;
do
{
   getInput();
   if (something)
     guard = false;
} while (guard)
这几乎是一回事

也许这更干净(因为所有循环信息都包含在块的顶部):


这并不是一件可怕的事情,但在编码时需要考虑其他开发人员。甚至在学校

您的开发伙伴应该能够在循环声明中看到您的循环的exit子句。你没有那么做。在循环的中间隐藏了Exchange子句,为其他来的人做更多的工作,并尝试理解代码。这与避免“中断”之类的事情的原因相同


尽管如此,在现实世界中的许多代码中仍然会看到类似的情况。

根据我的经验,在大多数情况下,循环都有“主”条件继续。这是应该写入while()运算符本身的条件。所有其他可能中断循环的条件都是次要的,不太重要,等等。它们可以作为附加的
if(){break}
语句编写

while(true)
通常令人困惑,可读性较差


我认为这些规则并没有涵盖100%的情况,但可能只涵盖其中的98%。

从某种意义上讲,结构化编程结构比(有些非结构化的)中断和继续语句更受欢迎,这是不好的。相比之下,根据这一原则,他们更倾向于“转到”


我一直建议您尽可能使代码结构化。。。尽管如此,正如乔恩·斯基特所指出的,不要让它更结构化

通常用于读取输入的Java约定是:

import java.io.*;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String strLine;

while ((strLine = br.readLine()) != null) {
  // do something with the line
}
#include <iostream>
#include <string>
std::string data;
while(std::readline(std::cin, data)) {
  // do something with the line
}

和通常的C++输入约定:

import java.io.*;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String strLine;

while ((strLine = br.readLine()) != null) {
  // do something with the line
}
#include <iostream>
#include <string>
std::string data;
while(std::readline(std::cin, data)) {
  // do something with the line
}

因此,虽然在某些情况下,
break
goto
是合理的,但如果您所做的只是逐行读取文件或控制台中的数据,那么您就不需要
while(true)
循环来完成它——您的编程语言已经为您提供了使用输入命令作为循环条件的适当习惯用法。

道格拉斯·克罗克福德(Douglas Crockford)曾说过,他希望JavaScript包含一个
循环
结构:

loop
{
  ...code...
}
我也不认为Java拥有
循环
结构会更糟糕

while(true)
循环本身并没有什么问题,但教师往往会阻止它们。从教学的角度来看,很容易让学生创造出无止境的循环,而不理解为什么循环永远无法逃脱

但是什么呢
import java.io.*;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;

while ((line = br.readLine()) != null  && !line.equals("quit") ) {
  // do something with the line
}
loop
{
  ...code...
}
while( a() )
{
  fn();
}
loop
{
  if ( !a() ) break;
  fn();
}
do
{
  fn();
} while( a() );
loop
{
  fn();
  if ( !a() ) break;
}
for ( a(); b(); c() )
{
  fn();
}
a();
loop
{
  if ( !b() ) break;
  fn();
  c();
}
do {
   input = get_input();
   valid = check_input_validity(input);    
} while(! valid)
input = get_input();
while(input_is_not_valid(input)) {
    disp_msg_invalid_input();
    input = get_input();
}
do {
    input = get_input();
    if (input_is_valid(input)) {
        break;
    }
    disp_msg_invalid_input();
} while(true);
while(true) {
   do_stuff();
   if(exit_time) {
      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);
      }
  }
DWORD dwError = ERROR_SUCCESS;

do
{
    if ( (dwError = SomeFunction()) != ERROR_SUCCESS )
    {
         /* handle error */
         continue;
    }

    if ( (dwError = SomeOtherFunction()) != ERROR_SUCCESS )
    {
         /* handle error */
         continue;
    }
}
while ( 0 );

if ( dwError != ERROR_SUCCESS )
{
    /* resource cleanup */
}
x = read_value_from_database()
while (true) 
 if (x == 1)
  ...
  break;
 else if (x ==2)
  ...
  break;
and lots more else if conditions
}
do {
  // Imagine a nice chunk of code here
} while(true);

do {
  // Imagine a nice chunk of code here
} while(price < priceAllowedForDiscount);