Reputation: 29
Why this code is wrong ? When I change "else if(this.power >= p)"
into only "else"
, it's right. Can anybody give me a hint?
public boolean useBattery(double p) {
if(this.power < p) {
this.power = 0.0;
return false;
} else if(this.power >= p) {
this.power = this.power - p;
return true;
}
}
Upvotes: 1
Views: 160
Reputation: 59095
To a human reader looking at the code it seems that either the first return
will be hit, or the second, but the compiler can't be sure. To the compiler it looks like:
if (condition1) {
...
return false;
} else if (condition2) {
...
return true;
}
and it needs to know, what will the method return if neither condition1
nor condition2
is true?
Whereas if you change it to a straight else
,
if (condition1) {
...
return false;
} else {
...
return true;
}
then it is certain that one of the two return
statements must be hit.
In fact in your method there is a chance that neither condition will be met: if one of the numbers you are comparing is NaN
(the special floating point value representing "not a number"), then both of your if
conditions will be false, and the method would have no return value.
There is also theoretically a possibility that some code running in another thread might alter the value of this.power
between the first if
check and the second, which could lead to both conditions evaluating to false. So it is not possible for the compiler to know for certain that one of the conditions will be met, even if they were logically complementary.
Upvotes: 6
Reputation: 13436
You can reproduce this error with even shorter code:
public int doSomething() {
if(true) {
return 0;
}
}
This method generates compiler error missing return statement
Compiler doesn't perform intelligent static analysis of your code. It just checks statements according to specification.
Java Language Specification 8.4.7 "Method body" states that:
If a method is declared to have a return type, then a compile-time error occurs if the body of the method can complete normally.
So, compiler just checks if these statements can complete normally.
JLS 14.9.1 "The if-then Statement":
If the value is true, then the contained Statement is executed; the if-then statement completes normally if and only if execution of the Statement completes normally.
If the value is false, no further action is taken and the if-then statement completes normally.
As you can see by specification if statement can complete normally. That's why a compile-time error occurs.
On the other hand, by JLS 14.9.2 "The if-then-else Statement":
If the value is true, then the first contained Statement (the one before the else keyword) is executed; the if-then-else statement completes normally if and only if execution of that statement completes normally.
If the value is false, then the second contained Statement (the one after the else keyword) is executed; the if-then-else statement completes normally if and only if execution of that statement completes normally.
As you can see if-then-else completes if and only if one of its blocks completes normally. In your example both of them contain return statements.
Upvotes: 1
Reputation: 106390
What happens if we don't enter any of your conditional branches? Java can't determine that you'll be able to because else if
implies that there may not be another conditional branch to check.
Phrased another way, there's an implicit else
block that does nothing. Since you declare a return type, having this implicit else
block do nothing is an error.
An else
block is always guaranteed to execute, so you will not run into the same situation with else
, which is probably what you intended to use in the first place.
Think in the case of a flowchart.
this.power < p
), then
power
to 0this.power >= p
), then
p
from power
Upvotes: 3
Reputation: 5087
Because if you add if into the second else there might be a condition where neither of the condition will be satisfied and method will match to no return statement.
Consider this simple example:
Consider x=5; below code will match no return statement because it doesn't satisfies any condition.
if(x>5){
return true;
}
else if(x < 5){
return false;
}
Upvotes: 1