Yes, indeed that was my point. My innitial prediction was
that the second code would also compile and print the same result, but
it did not. The Java compiler should be more consistent: it should
detect both cases ('if else' and 'if if') or it should complain on
both. I saw this code on a Java test; for such questions your only
solution is to remember how the compiler behaves. I don't like things
that you just have to remember.
I disagree. The rules for "if else" are far easier, more deterministic,
and allow for less loopholes than your artificially constructed "if if"
scenario. When you have an "if else" construct, it is a fact that
*always* *exactly one* of the "if" and "else" branches shall be
followed.
However, in your "if if" case, you have to separate "if" statements,
which happen to coincide by having exactly opposite criteria. A human
will be able to look at both at the same time, understand that the
value of an int variable is *always* *either* more than 10 *or* less
than or equal to 10 (paraphrasing your original code), but
automatically deducing this from a set of program statements requires
quite an advanced algorithm, when done by an automaton that can only
ever do what it is told to do, with no intuition or bright ideas of
its own. Here's a rough outline of what it would have to do:
- Note the first "if" statement and store both operands of its
criterion to memory for late comparison,
- Note the execution branch of the "if" statement as a currently open
execution path,
- Note that there is no code between the two "if" statements that might
diverge program flow away from the second "if" statement,
- Note the second "if" statement and store both operands of its
criterion to memory,
- Note the execution branch of the "if" statement as a currently open
execution path,
- Compare the operands of both "if" statements, seeing that the first
operand is the same variable, the second operand is the same constant,
and the operators are directly opposite,
- Deduce that the criteria of the two "if" statements are directly
opposite,
- Use this information to close both open execution paths,
And only then proceed as it would have done *straight away* in the
"if else" case.
What if the variable in the second "if" statement was not i, but j, and
j was assigned a value from i? What if that assignment was done not in
the normal execution path, but an "if" statement whose criterion just
happened to be always true? What if there was a reassignment to j later,
but in a "for" loop that iterates exactly 0 times? What if j was first
decremented by two, then incremented by one, then again incremented by
one?
Go on, *you* try to write a formal, deterministic algorithm to take
care of all this. I suppose there are highly-paid research groups in a
couple of universities working on it. If you produce successful reports,
you could write an article about it in a computing magazine.
The issue gets even more interesting when the criteria for the "if"
statements come from methods in different objects. Sooner or later the
Java compiler will essentially have to run the program in order to find
out if it can compile it.
But for the "if else" case, there is only one simple rule: In every
"if else", no matter where it appears or what its criterion or
background state are, *exactly one* of its branches will *always*
execute. Not both, not neither, *exactly one*. All the compiler has to
do is to spot an "if" with an "else" and instantly arrive at this
conclusion.