&安培; vs&& - 如何使用第一种情况?

时间:2011-10-18 22:18:21

标签: java operators semantics

  

(a> b)& (c< d),从左到右评价组分,因此(a>   b)首先进行评估。如果(a> b)为假,则整个表达式为   不管组件的结果如何都是假的(r b)评估为假。这被称为短   短路。

在Java书中看到了这一段。我以前用各种语言编程,但我从未发现需要'&'。如果已知最终结果不受其影响,为什么要评估第二个语句?对它有用吗?这是由于历史原因吗?

同样的问题适用于|和||同样。

8 个答案:

答案 0 :(得分:2)

&& operator由Java语言规范定义,用于执行短路评估。

然而,&运算符不是,even when applied to boolean arguments

如果其中一个参数存在您不想要短路的副作用,您可以利用此功能。但是,根据我的经验,这种情况并不常见,而且您面临着某人“修理”它的风险。最好分成几个步骤。例如,而不是:

if ( foo() & bar() ) {... }
你可以说:

boolean isFoo = foo();
boolean isBar = bar();
if ( isFoo && isBar ) { ... }

答案 1 :(得分:2)

如果您希望代码受到来自timing attacks的攻击,您希望分支(条件执行路径)的数量最少,这是消除它们的一种方法

答案 2 :(得分:1)

也许第二次评估是以赋值语句或方法调用的形式,在这种情况下,您可能希望它执行。我不会使用按位运算符代替像这样的逻辑运算符。如果你需要执行传递&&的内容,那么在逻辑语句之前执行它并将结果存储在变量中。

答案 3 :(得分:1)

if(0 != ((a > b) ? 1 : 0) & ((c < d) ? 1 : 0)) {
   // but really... (a > b) && (c < d), assuming no side-effects
}

...只需使用logical operators&&||)了解条件; - )这就是设计的< / em>的。如果需要非短路行为,则相应地重新构造代码。

我想我已经看过一个案例在这种情况下对&的使用有点有效,但我不记得它是什么,所以我一定不能发现它有效;-)在像这样的语言中C / C ++中没有谨慎的“布尔”类型,&的(输入)和结果可以被处理为0 -> falsenon-0 -> true。然而,可以看出,Java必须通过一些乐趣来获得bool -> int -> bool

bit-wise operator的唯一理由是,按位运算,IMOHO。在执行某种编码(包括“位字段”和“位掩码”)时,按位运算符最有用。它们在处理Java的仅有符号字节等的乐趣时也很有用。

我认为带走的更大(仅限?)点是 &&||短路 - 它们实际上是只有具有此行为的运营商 (排除?:以外的参数);剩下的就是解释逐位运算符的急切行为。这只是重新强制执行规则:不会在条件中引起副作用(在一些广为接受的习语之外,但即使这样,也要保持简单)。

快乐的编码。


逐位使用的示例:

想象一下使用以序列化格式存储在单个“整数”插槽中的标志:

int flags = 0;
if (this.encypted) {
   flags |= EncryptedMode;
}
out.write(flags);

// later on
int flags = in.readInt();
this.encrypted = (flags & EncryptedMode) != 0;

读取字节的“无符号值”:

byte[] data = {-42, ...}; // read in from file or something
int unsignedByte = data[0] & 0xFF;

答案 4 :(得分:1)

您可以在必须评估两个子表达式的情况下使用&。例如,如果它们都具有可由您的应用程序的其余部分观察到的副作用。

答案 5 :(得分:1)

'&amp;'之间的区别和'&amp;&amp;'并不是众所周知,本书中的例子并没有多大帮助。

这是另一个展示短路工作的例子(使用带有副作用的可怕方法,但这不是重点)。

想象一下你有这个:

private int cnt;

private boolean a() {
    cnt++;
    return false;
}

private boolean b() {
    cnt++;
    return false;
}

如果执行以下操作:

    cnt = 0;
    if ( a() && b() ) {}
    System.out.println( cnt );

它将打印1。

如果您执行以下操作:

    cnt = 0;
    if ( a() & b() ) {}
    System.out.println( cnt );

它将打印2.因为在后一种情况下, b() 必须根据语言规范进行评估,而在第一种情况下 b()<根据语言规范, 不得进行评估。

答案 6 :(得分:0)

你的书令人困惑。在大多数情况下,您只能使用'&amp;&amp;'和'||'。单身,'&amp;'和'|'是按位运算符 - 您可以在这里阅读更多相关信息:http://download.oracle.com/javase/tutorial/java/nutsandbolts/op3.html

答案 7 :(得分:0)

使用非短路运算符可以通过避免分支误预测停顿来加速性能关键代码,这可能很容易达到十几个或更多时钟周期。