简体   繁体   English

评估尊重括号和优先权 - java

[英]Evaluation Respects Parentheses and Precedence - java

As per the Java Language Specification: 根据Java语言规范:

Evaluation Respects Parentheses and Precedence 评估尊重括号和优先顺序

aside from using mathematical operation like: 除了使用数学运算之外:

int i = 3;
int j =  3 * (9 + 3);
System.out.println(j); //results to 36

are there any other examples that this rule apply? 该规则是否适用于其他任何示例? I tried using 我试过用

int i = 0;
int z = 0;
if(i++ < 5 || (++z <0 && 5 > z++) || 6 < ++i){
  System.out.println("Routed here");
}
System.out.println("i: " + i);
System.out.println("z: " + z);

but it results to i: 1 and z:0. 但结果是i:1和z:0。 It seems that the evaluation on that if example is still from left to right. 似乎对该示例的评估仍然是从左到右。

With || 随着|| , Java uses the concept of short circuiting, while evaluating expressions. ,Java在评估表达式时使用了短路的概念。 Therefore, in this: 因此,在这:

if(i++ < 5 || (++z <0 && 5 > z++) || 6 < ++i){

since the very first expression i++ < 5 returns true, hence rest of the expression will not be evaluated, ie never visited, hence will bring a change only in the value of i and no other thingy. 因为第一个表达式i++ < 5返回true,因此表达式的其余部分将不会被评估,即从未被访问过,因此只会在i的值中带来变化,而不会有任何其他东西。

Quote from Java Docs: 来自Java Docs的引用:

The Conditional Operators The && and || 条件运算符&&和|| operators perform Conditional-AND and Conditional-OR operations on two boolean expressions. 运算符对两个布尔表达式执行条件AND和条件OR运算。 These operators exhibit "short-circuiting" behavior, which means that the second operand is evaluated only if needed. 这些运算符表现出“短路”行为,这意味着仅在需要时才评估第二个操作数。 && Conditional-AND || && Conditional-AND || Conditional-OR The following program, ConditionalDemo1, tests these operators: Conditional-OR以下程序ConditionalDemo1测试这些运算符:
class ConditionalDemo1 {

    public static void main(String[] args){
        int value1 = 1;
        int value2 = 2;
        if((value1 == 1) && (value2 == 2))
            System.out.println("value1 is 1 AND value2 is 2");
        if((value1 == 1) || (value2 == 1))
            System.out.println("value1 is 1 OR value2 is 1");
    }
}

Parentheses and precedence don't have anything to do with the order in which expressions are evaluated at run time. 括号和优先级与运行时计算表达式的顺序无关。 That is, if you think putting parentheses around an expression means that it will get evaluated earlier, or that an operator with higher precedence is evaluated earlier, you're misunderstanding the concept. 也就是说,如果您认为在表达式周围加括号意味着它将在之前得到评估,或者更早地评估具有更高优先级的运算符,那么您就会误解这个概念。

Operator precedence answers questions like this: In the expression 运算符优先级回答如下问题:在表达式中

a * b + c

Which operator does the compiler "bind" to arguments first? 编译器首先将哪个运算符“绑定”到参数? If + had a higher precedence, it would grab the arguments near it before * could, so to speak; 如果+具有更高的优先级,它会在*之前抓住它附近的参数,可以这么说; so that the result would be that b and c are added, and the result is multiplied by a . 这样结果就是添加了bc ,结果乘以a That is, it would be equivalent to 也就是说,它等同于

a * (b + c)

But in most programming languages (with some exceptions such as APL), the * has higher precedence. 但在大多数编程语言中(有一些例外,如APL), *具有更高的优先级。 That means the arguments are bound to * before they're bound to + , which means that a and b are multiplied, and the result is added to c , ie 这意味着参数在绑定到+之前绑定到* ,这意味着ab相乘,并且结果被添加到c ,即

(a * b) + c

Similarly, in the expression 同样,在表达式中

a + b * c

the result is that b and c are multiplied, and the result is added to a . 结果是bc相乘,结果加到a

a + (b * c)

You can put parentheses around parts of the expressions to change how the arguments are bound; 您可以在表达式的某些部分周围加上括号来更改参数的绑定方式; thus, if you want to add a and b and multiply the sum by c , you can say 因此,如果你想添加ab并将总和乘以c ,你可以说

(a + b) * c

But it's very important to note: All this controls how the expression is interpreted at compile time. 但是需要注意的是:所有这些都控制在编译时如何解释表达式。 But at runtime, the arguments are always evaluated left-to-right. 但是在运行时,参数总是从左到右进行评估。 When the program is run, ALL of the above expressions will cause the program to evaluate a , then b , then c . 当程序运行时,所有上述表达式将导致程序评估a ,然后是b ,然后是c This doesn't matter if a , b , and c are variables, but if they were method calls, it could possibly matter. 如果abc是变量,这无关紧要,但如果它们是方法调用,则可能很重要。 In Java, when the program is run, things are always evaluated from left to right. 在Java中,当程序运行时,事物总是从左到右进行评估。 (This is not true of other languages; most languages that I know of let the compiler choose the order.) (其他语言并非如此;我所知道的大多数语言都让编译器选择顺序。)

And when it comes to || 当涉及到|| and && (or similar operators in some other languages), once again at run time, the left argument is always evaluated first. && (或其他一些语言中的类似运算符),再次在运行时, 始终首先计算左参数。 The right argument may or may not be evaluated. 可能会或可能不会评估正确的参数。 Parentheses and operator precedence control how the expression is interpreted if you have an expression like some-expression-1 || some-expression-2 && some-expression-3 如果你有一个像some-expression-1 || some-expression-2 && some-expression-3这样some-expression-1 || some-expression-2 && some-expression-3括号和运算符优先级控制表达式的解释方式 some-expression-1 || some-expression-2 && some-expression-3 , but they do not change the order of evaluation at run time. some-expression-1 || some-expression-2 && some-expression-3 ,但它们不会在运行时更改评估顺序。

As soon as the test can be evaluated to true or false the execution jumps inside the if block. 只要测试可以被评估为true或false,执行就会在if块内跳转。 In your case, i equals 0 which is lighter than than 5 so the test evaluates to true . 在你的情况下, i等于0 ,它比5轻,所以测试评估为true

(true OR a OR b) is true independently from the values of a and b , which are not evaluated (and incrementations are not applied). (true OR a OR b)ab的值无关,它们不被评估(并且不应用增量)。

It would be the same with (false AND a AND b) except it would always skip the block. 它将与(false AND a AND b)相同,除非它总是跳过块。

Check the order of your expressions, split them into separate tests or get your incrementations out of the test. 检查表达式的顺序,将它们分成单独的测试或从测试中获得增量。 The following code is equivalent to your example but with the output you expected : 以下代码等同于您的示例,但具有您期望的输出:

int i = 0;
int z = 1;
if(i < 5 || (z < 0 && 5 > z+2) || 6 < i+2){
  System.out.println("Routed here");
}
i += 2;
z += 2;
System.out.println("i: " + i);
System.out.println("z: " + z);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM