我已经用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(正确)怎么了?
这是你的枪,你的子弹和你的脚…
说它不好是因为你在自找麻烦。你或本页上的任何其他海报都不会有简短的while循环的例子。
麻烦将在未来某个非常随机的时间开始。可能是其他程序员造成的。可能是安装软件的人。可能是最终用户。
为什么?我必须找出为什么700K的LOC应用程序会逐渐开始消耗100%的CPU时间,直到每个CPU都饱和。这是一个神奇的while (true)循环。这件事又大又恶心,但归结起来就是:
x = read_value_from_database()
while (true)
if (x == 1)
...
break;
else if (x ==2)
...
break;
and lots more else if conditions
}
没有最后的其他分支。如果值不匹配If条件,循环将一直运行到时间结束。
当然,程序员指责最终用户没有选择程序员期望的值。(然后我在代码中删除了while(true)的所有实例。)
恕我直言,使用while(true)这样的结构并不是很好的防御性编程。它会回来困扰你的。
(但我确实记得,如果我们不评论每一行,教授就会扣分,即使是i++;)
Douglas Crockford说过,他多么希望JavaScript包含一个循环结构:
loop
{
...code...
}
我也不认为Java会因为拥有循环结构而变得更糟糕。
while(true)循环本身并没有什么错,但是老师们倾向于不鼓励它们。从教学的角度来看,很容易让学生创造出无穷无尽的循环,而不理解为什么循环没有被转义。
但是他们很少提到的是,所有的循环机制都可以用while(true)循环复制。
while( a() )
{
fn();
}
和
loop
{
if ( !a() ) break;
fn();
}
and
do
{
fn();
} while( a() );
等于:
loop
{
fn();
if ( !a() ) break;
}
and
for ( a(); b(); c() )
{
fn();
}
等于:
a();
loop
{
if ( !b() ) break;
fn();
c();
}
只要你能以一种工作的方式设置你的循环,你选择使用的结构是不重要的。如果它恰好适合for循环,则使用for循环。
最后一点:保持循环的简单性。如果在每次迭代中都需要执行许多功能,那么就将其放入一个函数中。在你让它工作之后,你总是可以优化它。