This question already has answers here:
Why is this code giving an "Unreachable Statement" error?
(4 answers)
Closed 4 years ago.
As part of my APCS course, I have to fix little problems in a program that's already been written so it can be referenced later. This section is on while-loops and I never learned about unreachable statements so I don't have a clue how to go about fixing it. Attached is the while loop from the program. The error shows up at the first curly bracket.
while( false ) {
//Since the guess doesn't match, determine if it is too low or too high.
if (userGuess > secretNumber) {
System.out.print("Guess number " + numGuesses + " is too LOW. ");
}
else if (userGuess < secretNumber) {
System.out.print("Guess number " + numGuesses + " is too HIGH. ");
}
}
The specific part of the language spec (for Java 9, at least) is Sec 14.21, which describes the conditions under which statements are considered unreachable.
In particular:
It is a compile-time error if a statement cannot be executed because it is unreachable.
and (emphases mine):
A while statement can complete normally iff at least one of the following is true:
The while statement is reachable and the condition expression is not a constant expression (§15.28) with value true.
There is a reachable break statement that exits the while statement.
The contained statement is reachable iff the while statement is reachable and the condition expression is not a constant expression whose value is false.
So, the body of your while loop is considered unreachable because the value of the expression is false, and because it's constant.
To fix it, change either of those conditions; or remove the while loop, since it doesn't logically do anything anyway.
while(false){//...} line will never allow the code to reach either the inner if or the else statement.
The if and else statement will be only evaluated if the condition expression in the while construct is not a constant false, which is not the case in your code.
Hence, the compiler complains that your if & else statements cannot be reached in the current scenario.
You can instead use a variable and assign it the boolean value, as demonstrated by Mr. Elliott Frisch in his answer.
With the loop construct while ( boolean ) the body of the loop is only entered if boolean evaluates to true. A boolean literal false cannot evaluate to true, thus the body is unreachable code.
boolean loopControl = false;
while ( loopControl ) { // <-- this is fine ..
// ...
}
Related
I have a program I need to implement that has the following code:
for (int n = 1024; true; n+=n)
I cannot find any other examples of java loops having such a format. What does this mean? I've tried to research it, but I don't even know what to search for - it's totally foreign to me.
The basic for statement is described in the language spec:
for ( [ForInit] ; [Expression] ; [ForUpdate] ) Statement
You are asking about the case when Expression is true. (The square brackets above mean it is optional).
The meaning of that is described just below, in Sec 14.14.1.2:
If the Expression is not present, or it is present and the value resulting from its evaluation (including any possible unboxing) is true, then the contained Statement is executed.
...
If the Expression is present and the value resulting from its evaluation (including any possible unboxing) is false, no further action is taken and the forstatement completes normally.
So, Expression is present, and evaluates to true (because true evaluates to true). Hence, Statement is executed, and will continue to be executed because Expression remains true.
As such, it is an infinite loop (unless there is a break, return, throw or System.exit inside the loop).
Why you dont use another loop? Use for example do-while instead of
for (int n = 1024; true; n+=n)
You can make a work around with:
int n=1024;
do{
//your code
n+=n;
}while(condition==false);
I apologize if this question has been asked somewhere in Empty for loop - for(;;) or else where on the site.
I was wondering if any one knows why java would choose for their parser/compiler to evaluate an empty conditional statement in a for(;;){} loop as true instead of perhaps null or void ?
as linked by user #Mchi
https://developer.mozilla.org/en/JavaScript/Reference/Statements/for
"An expression to be evaluated before each loop iteration. If this expression evaluates to true, statement is executed. This conditional test is optional. If omitted, the condition always evaluates to true. If the expression evaluates to false, execution skips to the first expression following the for construct."
I am just curious.
A conditional statement must be of boolean type in order to control looping, in exactly the same way that the expression within an if() or a while() statement must be of boolean type.
The only valid values for boolean are true and false. So, null and void are not applicable, they do not make any sense.
As for empty conditional statements, of the two possible values true and false, they chose true because there is absolutely never any need for a loop that will not loop at all, while there are plenty of situations where we have a need for a loop that will loop forever (or until break.)
This question already has answers here:
Java do while loop making string testing act differently
(3 answers)
Closed 6 years ago.
First let me start off by saying I'm new to Java and I'm not a professional programmer but I have written several macros in VBA.
I'm trying to help my son with his high school Java assignment. In the assignment there is a point where the user has a Y or N input. I can't figure out why this code doesn't work.
// Wait for user to press Y or N
do{
playAgain = input.next();
} while (!playAgain.equalsIgnoreCase("n") || (!playAgain.equalsIgnoreCase("y"));
It works if I only check for one condition.
Your logic says to continue looping so long as the input does not equal n/N or y/Y. This will always be true for both yes and no inputs, and in fact all inputs. If no is entered, the first condition would fail, but the second would be true, and vice-versa for yes.
To remedy this, you should && together the two conditions:
do {
playAgain = input.next();
} while (!playAgain.equalsIgnoreCase("n") && (!playAgain.equalsIgnoreCase("y"));
|| means OR. So, A || B is true if A is true or B is true. Any Or condition works like this: If first part if true, then second condition is not evaluated. If first is false, then second is evaluated. If either is true, then the result is true.
In your do while loop: !playAgain.equalsIgnoreCase("n") will be true if "y" is equal to your input and vice versa. Either way any one of the condition will always be true in the while loop condition, so the loop will go forever. The solution is mentioned in the answer given above. (use && instead of ||)
Why do the following raise an error?
for(; 0 ;) System.out.println("guess"); // or
for(;false;) System.out.println("guess"); // or
for(; 1 ;) System.out.println("guess");
But the following runs okay (infinitely):
for(;true;) System.out.println("guess");
Why does it work for true but not for false?
The condition (i.e. the bit between the ;s) must be a boolean, so this immediately rules out the first and third variants in your first snippet.
Now, the second variant, in which you have used a boolean, doesn't compile because the compiler realizes that the loop will never be entered and hence issues an error:
Untitled.java:3: error: unreachable statement
for(;false;) System.out.println("guess");
^
1 error
Note that the JLS mandates that errors be issued for unreachable statements (see §14.21):
It is a compile-time error if a statement cannot be executed because it is unreachable.
...
The contained statement is reachable iff the for statement is reachable and the condition expression is not a constant expression whose value is false.
Java requires a boolean as second parameter in your loop header, it evaluates the statement and if the statement returns true the jvm will run the code of the loop-body, not the body will be skipped.
0 and 1 are obviously no booleans nor do they define a statement which could be evaluated (like x < y) and since java is a static and strong typed language (unlike Python or Perl) it cannot cast an int to a boolean, so it crashes.
Edit: If you provide "false" as statement the JVM will notice that the loop-body never can be reached, this will cause a runtime-error.
Unlike C, in Java, true and false correspond to boolean type values, where 1 and 0 to int (in fact, in C there is no boolean declarative type, and boolean checks are done based on integer comparisons. In Java, things are distinct).
I had an if statement checking some value, And encountered a weird bug(Not sure!). My code was incorrect syntactically and in result it produced a wrong result, however eclipse didn't raised any error while compiling. Why My below code worked?
if((this.trackPointList.get(point).getTurnOutId().equals(seg.getSegRef().getTurnOut())) && seg.getSegRef().getKind().equals("arc")); // <---- See here I have semicolon
{
... code to run ...
}
Above code check only first condition and ignores seg.getSegRef().getKind().equals("arc") but I guess this should raised an issue at compile time, Am I right? My logic worked once I debugged it by skimming line by line and found this semicolon. I will appreciate if someone could explain, if it is a valid syntax.
Enlighten Me, Please!
The ; makes Java think that the body of the if conditional is complete, even if there is no other code preceding it. In effect, the code in the if statement is executed, but no body exists because the ; is there.
The { ...code to run...} is just a code block that executes, and anything declared inside that block is not visible outside the block. It will always run here because it's not part of the if block.
edit: here's another stack overflow question about the { } blocks: What do curly braces in Java mean by themselves?
The code is syntactically correct. You can write ifs without braces, like:
if(condition) statement;
Having empty statements is also valid. For instance this code is valid:
int a = 0;;
;;;
So an empty if is valid as well, although it doesn't make much sense :)
if(condition);
An if statement followed by a semicolon is called an "empty if statement".
It rarely is of any use, but it's syntactically legal.
You can write something like this
if ( doSomethingThatReturnsABoolean() )
; // Empty statement
else
doSomeOtherThing()
but it would be better to write
if ( !doSomethingThatReturnsABoolean() )
doSomeOtherThing()
Regarding your observation that only the first condition gets checked:
If the first condition returns false the second condition will not get checked, because
(false && secondCondition)
always equals to false, so the value of secondCondition is irrelevant.
The ; after the if(..) statement represents an empty statement that is executed conditionally when the if(..) evaluates to true. The { .. } represents a code block that always executes with it's own scope.
The second condition may be ignored if the first condition is false due to short-circuit evaluation.
if(condition); is equivalent to if(condition){}
same thing with for loop & while loop:
for(;condition;); is equivalent to for(;condition;){}
while(condition); is equivalent to while(condition){}