在Java中,while (x = false)和while (!x)有什么区别?

3

抱歉,我对Java还很陌生,所以这个问题可能不太清楚。

最近我一直在处理将try和catch语句放入while循环中的问题,因为我想确保获取输入被封闭在程序的其余部分之外。

我遇到了一个问题,在while条件中使用变量前面的感叹号(例如while(!done)),而不是使用= false(例如while(done = false)),会改变我的程序运行方式。

前者(!done)会按预期运行try和except语句。

后者(done = false)则不会,只是跳过它们并继续执行代码的下一部分。

我原本认为在变量前加上感叹号意味着与var = false相同。

我错了吗?

以下是一个例子:

import java.util.Scanner;

public class TestOne {
    public static void main(String args[]) {
        Scanner input = new Scanner(System.in);
        int num;
        boolean inputDone = false;
        while (!inputDone) {
            try {
                System.out.print("Enter in a number here: ");
                num = input.nextInt();
                inputDone = true;
            }
            catch (Exception e) {
                System.out.println(e);
                System.exit(0);
            }
        }
        System.out.println("Success!");
    }
}

目前,编译和运行程序都很顺利:它会提示我输入一个数字,输入字母或非常长的数字会导致打印出异常类型并退出。输入正常数字会导致打印Success!

另一方面,如果我将!inputDone替换为inputDone = false,则在运行程序时仅会打印出Success!

有人能向我解释while循环中!和= false语句之间的区别吗?


x == false 是不好的编程风格,几乎和 x == true 一样糟糕。 - starblue
我喜欢这个问题标题中的错别字是永远不会编写 lvalue == false 的原因。 - Pete Kirkham
8个回答

17
注意done = falsedone == false之间的差别。第一个将done赋值为false并且被评估为false,而第二个将donefalse进行比较并且完全等同于!done
因此,如果您使用:
while (done = false)
{
 // code here
}

接着,done被设置为false,而while循环内的代码则完全不会被执行。


谢谢。 这是我最近第二次忘记那个叹号的第二个错误。 - akbiggs
3
如果你不再养成将布尔值与'=='显式比较的(不良)习惯,那么你就不会犯这个错误了。 - Stephen C

4
声明 x = false 是一个赋值语句 - 你正在将 x 设置为 false。然而,语句 x == false!x 是相同的。语句 x == false 将 x 与 false 进行比较,如果 x 的值为 false,则结果为 true,如果 x 的值为 true,则结果为 false。语句 !x 将导致对 x 的值进行取反。
在您的代码中,如果您使用 while(inputDone == false) 替换 while (!inputDone),则会得到预期的行为。

哦,哈哈。哇,我真不敢相信我错过了那个。谢谢! - akbiggs

3

在比较操作符中,你需要使用==而不是=


2

表达式:

x = false

意思是将x赋值为false

在你的while()中发生这种情况后,它会评估x,由于它的值为false,因此根本不会进入循环。

另一方面:

while (!x)

意思是“只要!x为真,就继续进入循环”。因为!x的意思是“x的相反数”。所以只要x为假,循环就会继续。


2
"

while(done = false)" 等同于 "done=false; while(done)"。

应该写成 "while(done == false)" 或者 "while(false == done)"。

但是,!done 是最易读的代码,它表示“NOT DONE”。


写作"while (done == false) ..." 对我来说效果最好。 我往往会忽略那些讨厌的感叹号。 - Thorbjørn Ravn Andersen

2
正如其他人指出的那样,你打错了“==”。更有趣的是与此相关的问题。
对于设计语言来说:鼓励表达式中的副作用是不好的。使用符号“==”表示数学上的“=”并不是一个好选择。
就可读性而言,“!done”比“done == false”更易读 - 我们想要“未完成”(在我看来,“直到完成”比“当未完成时”更好)。虽然(长期)新手经常写冗余的“someCondition == true”。
使变量成为“final”是一个好主意,尽管在这种情况下显然不可行。然而,我们可以通过使用“break”语句完全删除标志。少数人遵循单入口单退出(SESE)规则,禁止使用“break”,这将使这个例子更加棘手(您需要测试以查看文本是否为有效的“int”,或者在这种情况下,将主体移动到循环中)。

1

其他答案已经提到,写 x == falsex == true 是不好的风格。这有三个原因:

  • 简洁性:假设您在需要布尔值的上下文中,且“x”是一个布尔值,则写x比写x == true!x比写x == false更少字符。
  • 约定:Java(或C、C++、C#和大多数其他语言)中经验丰富的程序员都希望看到x而不是x == true,以及!x而不是x == false
  • 健壮性:在Java中,所有条件和循环语句都需要一个布尔值表达式作为条件。如果y不是布尔值,则形式为if (y = foo) {的笔误将在Java中导致编译错误。但是,如果y是布尔值,则if (y = foo) {不会导致编译错误。因此,通过避免对布尔值使用==,可以避免由笔误导致的一系列错误。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接