&与&& -- 第一种情况如何使用?

发布于 2024-12-10 09:44:53 字数 414 浏览 0 评论 0原文

(a>b)& (c < d),从左到右计算分量,因此 (a > d) b) 首先进行评估。如果 (a > b) 为假,则整个表达式为 无论组件的结果如何(r < d),均为 false。尽管如此, 组件(c<d)仍将被评估。然而,在 表达式 (a > b) && (c < d),分量 (c < d) 将不会 如果 (a > b) 计算结果为 false,则计算该值。这就是所谓的短 电路。

在一本Java书籍中看到这一段。我以前一直用各种语言编程,但我从未发现需要“&”。如果知道最终结果不受第二个语句的影响,为什么还要评估第二个语句呢?有什么用吗?它的到来是由于历史原因吗?

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

(a > b) & (c < d), the components are evaluated left to right, so (a >
b) is evaluated first. If (a > b) is false, the entire expression is
false regardless of the result of the component (r < d). Nevertheless,
the component (c < d) will still be evaluated. However, in the
expression (a > b) && (c < d), the component (c < d) will not be
evaluated if (a > b) evaluates to false. This is known as short
circuiting.

Came across this paragraph in a Java book. I have been programming in various languages before, but I've never found a need for '&'. Why would one want to evaluate the second statement if it's known that the end result is not affected by it? Is there any use for it; does it come due to historical reasons?

Same question applies to | and || as well.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

堇年纸鸢 2024-12-17 09:44:53

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

然而,&运算符不是,即使应用于布尔参数< /a>.

如果其中一个参数具有您不希望短路的副作用,您可以利用这一点。然而,根据我的经验,这种情况并不常见,您将面临有人“修复”它的风险。最好分成步骤。例如,

if ( foo() & bar() ) {... }

您可以说:

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

The && operator is defined by the Java Language Specification to perform short-circuit evaluation.

However, the & operator is not, even when applied to boolean arguments.

You could exploit this if one of the arguments had side-effects that you did not want short-circuited. However, in my experience this is uncommon, and you'd face the risk of someone "fixing" it. It would be better separated into steps. For example, instead of:

if ( foo() & bar() ) {... }

you could say:

boolean isFoo = foo();
boolean isBar = bar();
if ( isFoo && isBar ) { ... }
2024-12-17 09:44:53

如果您预计您的代码会受到定时攻击的攻击,您需要最少数量的分支(有条件的)执行路径)可能,这是消除它们的一种方法

if you expect your code to be under attack from timing attacks you want the least amount of branches (conditional execution paths) possible, this is one way to eliminate them

青巷忧颜 2024-12-17 09:44:53

'&' 之间的区别和“&&”并不出名,书中的例子也没有多大帮助。

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

想象一下你有这样的情况:

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() 不得进行评估。

The difference between '&' and '&&' is not well-known and that example from the book doesn't help much.

Here's another example to show how short-circuiting work (using horrible methods having side-effects, but that's not the point).

Imagine you have this:

private int cnt;

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

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

If you execute the following:

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

It shall print 1.

While if you execute the following:

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

It shall print 2. Because in the latter case b() must be evaluated as per the language specs while in the first case b() must not be evaluated, as per the language specs.

烟花肆意 2024-12-17 09:44:53

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

You can use & in situations where you have to evaluate both subexpressions. For example, if they both have side effects that are observable by the rest of your application.

蓝礼 2024-12-17 09:44:53

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

Perhaps the 2nd evaluation is in the form of an assignment statement or method call, in which case you might want it to execute. I wouldn't use bitwise operators in place of logical operators like this tho. If you need something to execute passed &&, then do it prior to your logical statement and store the result in a variable.

静待花开 2024-12-17 09:44:53
if(0 != ((a > b) ? 1 : 0) & ((c < d) ? 1 : 0)) {
   // but really... (a > b) && (c < d), assuming no side-effects
}

...只需使用逻辑运算符 (&& 和 ||) 用于条件;-)这就是它们设计的目的。如果需要非短路行为,则相应地重构代码。

我想我见过一个在这种情况下使用 & 的案例,但我不记得它是什么,所以我一定没有发现它是有效的;-) 在语言中就像没有谨慎的“布尔”类型的 C/C++ 一样,& 的(输入)和结果可以被处理为 0 ->; false非 0 ->正确。然而,正如我们所看到的,Java 必须跳过一些有趣的过程才能获得 bool -> 。整数->布尔

按位运算符的唯一理由是按位操作,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;
if(0 != ((a > b) ? 1 : 0) & ((c < d) ? 1 : 0)) {
   // but really... (a > b) && (c < d), assuming no side-effects
}

...just use the logical operators (&& and ||) for conditions ;-) That is what they were designed for. If non-shortcircuit behavior is required, then restructure the code accordingly.

I think I have seen one case that had a somewhat valid use of & in this context, but I do not recall what it was so I mustn't have found it that valid ;-) In languages like C/C++ where there is no discreet "boolean" type, the (input) and result of & can be treated such that 0 -> false and non-0 -> true. As can be seen, however, Java has to jump through some fun to get bool -> int -> bool.

The only justification for a bit-wise operator is, well, bit-wise operations, IMOHO. Bit-wise operators are most useful when performing some sort of encoding including "bit fields" and "bit masks". They are also useful when dealing with fun arising from Java's signed-only bytes, etc.

I think the bigger (only?) point to take away is that && and || are short-circuiting -- they are actually the only operators with this behavior (arguments over ?: excluded); the rest is just to explain the eager-behavior of bit-wise operators. This just goes to re-enforce the rule: do not cause side-effects in conditionals (outside of a few well-accepted idioms, but even then, keep it simple).

Happy coding.


Examples of bit-wise usage:

Imagine the use of flags which are stored into a single "integer" slot in a serialized format:

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

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

Reading the "unsigned value" of a byte:

byte[] data = {-42, ...}; // read in from file or something
int unsignedByte = data[0] & 0xFF;
顾挽 2024-12-17 09:44:53

你的书让事情变得混乱。大多数情况下,您只会使用“&&”和“||”。单个的“&”和 '|' 是按位运算符 - 您可以在此处阅读有关它们的更多信息: http://download.oracle.com/javase/tutorial/java/nutsandbolts/op3.html

Your book is confusing things. For the most part, you will only use '&&' and '||'. The single ones, '&' and '|', are bitwise operators - you can read more about them here: http://download.oracle.com/javase/tutorial/java/nutsandbolts/op3.html

浮光之海 2024-12-17 09:44:53

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

The use of a non-short-circuit operator may speed up performance-critical code by avoiding branch mis-prediction stalls, which could easily amount to a dozen or more clock cycles.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文