No I won't kick you to the beginner forum since this question is interesting on the SCJP point of view. Let's dig into it. Actually the code example you give boils down to the following expression: A || B && C (whether A, B and C are boolean primitive variables, boolean literals or boolean-returning methods is not important.) Java evaluates expression from the left to the right respecting the precedence order. In this case, when the runtime starts evaluating this expression it sees that it has to deal with a || (short-circuit OR) operation. It also sees that the first operand is A and the second is, well, it doesn't need to know that until A has been evaluated. When starting the evaluation of the expression what the runtime sees is A || ?? If the runtime finds out that A evaluates to false, then it will investigate further and evaluate the second operand which is B && C. But in this case, the runtime figures out that B is true and that there is thus no need to go further. That's why only A gets printed out. [ February 07, 2003: Message edited by: Valentin Crettaz ]
I suspected something along these lines, but I fail to see the role that precedence plays then... I can understand that this is possible as an optimization, but isn't it true that the || should be ignored until the && is complete? I could be missing the point (and didn't have much sleep last night)
Joined: Aug 26, 2001
Could you please take a look at the following document and tell me if it is of any help: http://www.atkinson.yorku.ca/~sychen/ITEC1620/Tutorial3.pdf Java performs what we call automatic binding, that is, the following expression A && B || C && D will be evaluated as (A && B) || (C && D) and not as A && (B || (C && D)) or as A && (B || C) && D In our case, A || B && C will be evaluated as A || (B && C) but since || is a short circuit the second operand never gets evaluated if A is true. [ February 07, 2003: Message edited by: Valentin Crettaz ]
Joined: Jan 31, 2002
I found a possible answer in this thread. I guessed I missed it in the JLS etc. No doubt that it could be hidden there somewhere. Will look at the PDF now as well. Thanks.
1. in the 1st if statement. the order of evaluation review the left poriton of the short circuit OR first. then, the short circuit OR is evaluated. followed by any statements after the short circuit OR. the point being. for both && and | |, the statement to the left are evaluated before operator precedence is applied. since the left operator is TRUE. the operator to the right of | | is never evaluated. the operator to the right of && will always be evaluated. 2. ie. b is three b is less than 4 therefore the first statment is TRUE 2+3 is 5 5 is greater than 0 therefore the second statemend is TURH the answer is TRUE Hope this clears things up. Monty <hr></blockquote> [ February 07, 2003: Message edited by: Jim Crawford ]
I think this is the story (although there was a part about grammer that looked interesting as well)
From: Eric Blake (firstname.lastname@example.org) Subject: Re: Operator Precedence View: Complete Thread (20 articles) Original Format Newsgroups: comp.lang.java.programmer Date: 2001-04-13 19:21:30 PST "Scott D. Isaac" wrote: > .. > 12. Short-circuit: && > 13. Short-circuit: || .. > > However, I have found the JLS (section 15) to be vague about precedence. > While this is the order in which they are presented, there is no mention > that that is the order of precedence. It is explicitly stated within the grammar of chapter 15, but is lacking in the grammar of chapter 18, as well as the descriptive text of chapter 15. Hopefully the 3rd edition JLS will rectify this and make the chapter 18 grammar express precedence, as well as describe it better in the description. > > So, what's my beef you ask? > > Through experimentation, I have found that 12 and 13 are at the same level > of precedence. This contradicts what I have seen written and the JLS is > silent on this matter. The difference in precedence is observable when the first term evaluates as true. With (a||b)&&c, c must be evaluated if a is true. However, with a||(b&&c), the entire (b&&c) term is never evaluated, because || short-circuits. So, if || and && have equal precedence, a||b&&c is equivalent to (a||b)&&c, since they group left-to-right; you would get a side-effect from evaluating c in 6 of the 8 input cases, and a true result in only 3 of the 8. However, since && has a higher precedence, a||b&&c is equivalent to a||(b&&c), and you only get a sige-effect from c in 2 of the 8 input cases, and a true result in 5 of the 8. Here's a program to print out all the cases.
This program outputs (with some post-formatting applied): false false false a b false a b false a b false false false true a b false a b false a b false false true false a b c false a b c false a b c false false true true a b c true a b c true a b c true true false false a true a c false a true true false true a true a c true a true true true false a true a c false a true true true true a true a c true a true -- Eric Blake
[ February 07, 2003: Message edited by: Jim Crawford ]
Joined: Jan 31, 2002
Summary: You can express precedence with brackets: thus a || b && c becomes a || (b && c) which is easy to understand. The || still gets executed first and the brackets illustrate what is done according to precedence. Just like Valentin said, but I didn't make the connotation immediately. Cheers.
I agree we could say && has a greater precedence than ||. But we must be aware of the code that the compiler generates. Because if someone thinks that a||b&&c will be treated as a||(b&&c) there is a problem: even though both will yield the same result, if the evaluation of b and c has side effects, they will not happen. The point is that || and && will not short-circuit the same part of the remaining expression. If the expression consist of a serie of && a || operators with no interwined parentheses the output of javap shows the following two points: a) A true value before || will short-circuit the whole of the remaining expression. Thus no remaining side effects will occur. It is funny to say that remaining && operators have a greater precedence because their operands are not evaluated at all. b) A false value before && will short-circuit only up to the left operand of the first || to its right. Thus side effects are possible starting from the right operand of the cited ||. I guess this difference in the implementations of the two operators allows for the "strange" bigger precedence of && over ||. Here goes the code produced by the compiler for two examples:
Note that the real values of the variables will not matter to the code generated by the compiler; at least in this case. Waiting for comments