Consider simple example
private static String isPositive(int val) {
if (val > 0) {
return "yes";
} else {
return "no";
}
}
Here it's pretty straightforward: if val > 0
return yes
else return no
.
But after compilation, in bytecode, this if condition is reversed:
private static isPositive(I)Ljava/lang/String;
L0
LINENUMBER 12 L0
ILOAD 0
IFLE L1
L2
LINENUMBER 13 L2
LDC "yes"
ARETURN
L1
LINENUMBER 15 L1
FRAME SAME
LDC "no"
ARETURN
It checks: if val <= 0
then return no
, else return yes
.
First, I thought that <=
check is cheaper, and it's some kind of optimization. But if I change my initial code to
if (val <= 0) {
return "no";
} else {
return "yes";
}
it still will be reversed in bytecode:
L0
LINENUMBER 12 L0
ILOAD 0
IFGT L1
L2
LINENUMBER 13 L2
LDC "no"
ARETURN
L1
LINENUMBER 15 L1
FRAME SAME
LDC "yes"
ARETURN
So, is there a reason for such behavior? Can it be changed to straightforward?
Actually, reversing the condition is the most straight-forward compilation strategy possible. You write Java code matching the pattern
if(condition_fullfilled) {
somecode
}
which will get compiled to bytecode matching the pattern
goto_if_condition_not_fullfilled A_LABEL
compiled_somecode
A_LABEL:
Since the conditional branch says when to skip the conditional code, its condition must be the opposite of your source code saying when to execute the conditional code.
The example above, not having an else
part, demonstrates why there is no simple way of compiling if
with a conditional branch instruction having the same condition than your source code. It’s possible, but would require more than one branch instruction.
This straight-forward compilation strategy for if
statements without else
can easily expanded to handle else
as well. There is no reason to change the strategy, e.g. switching the order of the statements, when an else
clause is present.
Note that in your case, where both branches end in a return
statement, there is no difference between
if (val > 0) {
return "yes";
} else {
return "no";
}
and
if (val > 0) {
return "yes";
}
return "no";
anyway.
It is probably done like this so that the two blocks of code in the if
show up in the same order in the translated bytecode.
For example, this Java code:
if (val > 0) {
return "yes";
} else {
return "no";
}
Translates to something like this (pseudocode):
If val <= 0, then branch to L1
return "yes"
L1:
return "no"
Note that in the original Java code, the if
condition is checked to see if the first block of code should run, while in the translated bytecode the check is done to see if the branch should be taken (skipping over the first block of code). So it needs to check a complementary condition.
Can it be changed to straightforward?
Of course it would also be possible to preserve the condition, but then you would need to reverse the order of the two code blocks:
If val > 0, then branch to L1
return "no"
L1:
return "yes"
I would not say that this version is "more straighforward" than the previous one, though.
Anyway, why would you want to change it? Both versions should be just fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With