When I'm compiling this code
public static void main(String [] args) {
int x = 0;
while(false)
{
System.out.println(hello);
}
}
it is showing compile time error unreachable code.
But when I modified this code to
public static void main(String [] args) {
int x = 0;
boolean result = false;
while(result)
{
x=4;
}
}
it's working fine.
Can somebody tell me the reason behind this behavior.
It is because boolean result = false is not a constant expression whereas false is. If you try the code below, it won't compile either because result is now a constant:
final boolean result = false;
while(result) { x=4; }
However this would compile, because result is not a constant variable any longer:
final boolean result;
result = false;
while(result) { x=4; }
See also: Why does the Java compiler not understand this variable is always initialized? for a similar discussion.
Usage of constant false in the following statement
while(false)
is resolved to false at compilation time hence compiler complains for unreachable code.
But when you use a variable instead:
boolean result = false;
while(result)
compiler is not sure about the value of it at compile time and hence does not complain.
The behavior of the compiler is precisely specified in the Java Language Specification, Section 14.21. Unreachable Statements.
Here is a key quote, which directly addresses your question:
This section is devoted to a precise explanation of the word "reachable." The idea is that there must be some possible execution path from the beginning of the constructor, method, instance initializer, or static initializer that contains the statement to the statement itself. The analysis takes into account the structure of statements. Except for the special treatment of while, do, and for statements whose condition expression has the constant value true, the values of expressions are not taken into account in the flow analysis.
Java uses a simple flow analysis algorithm to find most common cases of unreachable code, and all such unreachable code blocks will be flagged as compile-time errors. That's why your "while (false) { ... }" statement produces an error.
Related
If I write
private void check(){
if(true)
return;
String a = "test";
}
Above code works normally, but if I write
private void check(){
return;
String a = "test";
}
The compiler/gradle in Android studio doesn't let this one through even though it's the same, and it says that the code after return in example 2 is unreachable.
I don't have any issues regarding this but I am eager to know why?
javac compiler does very little optimizations, so it simply does not "see" that if(true) is always true(but you should get a warning); but C1/C2 JIT compilers will - so that code will simply be a return, without an if statement.
This is explained by the Unreachable Statements part of the Java Language Specification.
There are quite a few rules, with an interesting special case. This is a compile time error :
while (false) {
// this code is unreachable
String something = "";
}
while this is not :
if (false) {
// this code is considered as reachable
String something = "";
}
The given reason is to allow some kind of conditional compilation, like :
static final boolean DEBUG = false;
...
if (DEBUG) { x=3; }
So in your case :
private void check(){
if(true)
return;
// NO compilation error
// this is conditional code
// and may be omitted by the compiler
String a = "test";
}
is not an error because of the special if treatment, using while instead is not accepted :
private void check(){
while(true)
return;
// "Unreachable statement" compilation error
String a = "test";
}
This is also en error :
private void check(){
if(true)
return;
else
return;
// "Unreachable statement" compilation error
String a = "test";
}
When it tries to compile it builds an abstract syntax tree. In the first case 'true' is an anonymous variable, so two branches will be added, even only one of them is possible. In the 2nd case, there is only one possible branch to create, which will never reach its end.
The difference is these require two different analyses to determine the behavior. The first example requires semantic analysis while the later requires syntactical analysis. Compilers are experts in syntax; this is what they are built to do. They often struggle with semantics, though. Performing static semantic analysis takes more effort from the compiler writers and can be extremely difficult to get correct in general.
I get the "The local variable string may not have been initialized" error with the following code. The code itself doesn't make sense it was written just for the sake of exercise.
public class StringExercise
{
public static void main(String[] args)
{
String string; // initializing here fixes the issue
for (int i = 0; i < 10; ++i)
{
if( (i % 4) == 2 )
{
string = "Number: " + i;
}
}
System.out.println(string); // this is marked as wrong by Eclipse
}
}
To get it working it is sufficient to initialize String as expressed in the comment above.
My question is why is it needed? The method println will never be given null and initialization will happen the first time the condition in the loop returns true. Am I doing something wrong or is it just Java being overcautious over programmer's errors? If the latter, how is it justified from the theoretical point of view?
My question is why is it needed?
Because even though your code is "logically" written so that string will indeed be initialized in the loop, the compiler doesn't know it. All it sees is:
for (loop; elements; here)
if (someCondition)
string = something;
In short: a compiler will not check the logic of your code; it it only smart enough as to check for syntax errors, but after that, the bytecode generation itself is "dumb".
And as Java requires that all variables be initialized before use, you get this compiler error.
The compiler can't guarantee that string = "Number: " + i; will be executed within your for and if.
This question already has answers here:
if(false) vs. while(false): unreachable code vs. dead code
(3 answers)
Closed 8 years ago.
If I have code like
public static void main(String args[]){
int x = 0;
while (false) { x=3; } //will not compile
}
compiler will complaint that x=3 is unreachable code but if I have code like
public static void main(String args[]){
int x = 0;
if (false) { x=3; }
for( int i = 0; i< 0; i++) x = 3;
}
then it compiles correctly though the code inside if statement and for loop is unreachable. Why is this redundancy not detected by java workflow logic ? Any usecase?
As described in Java Language Specification, this feature is reserved for "conditional compilation".
An example, described in the JLS, is that you may have a constant
static final boolean DEBUG = false;
and the code that uses this constant
if (DEBUG) { x=3; }
The idea is to provide a possibility to change DEBUG from true to false easily without making any other changes to the code, which would not be possible if the above code gave a compilation error.
The use case with the if condition is debugging. AFAIK it is explicitly allowed by the spec for if-statements (not for loops) to allow code like this:
class A {
final boolean debug = false;
void foo() {
if (debug) {
System.out.println("bar!");
}
...
}
}
You can later (or via debugger at runtime) change the value of debug to get output.
EDIT
As Christian pointed out in his comment, an answer linking to the spec can be found here.
Regarding the for loop, I thinks it's just that it's not as easy to detect as the use of a false constant inside a while loop.
Regarding the if, that was a deliberate choice to authorize it in order to be able to remove debugging code from the byte code at compilation time:
private static final boolean DEBUG = false; // or true
...
if (DEBUG) {
...
}
class string1 {
static public void main(String[] ar) {
String s1 = "test";
String s2 = new String();
if(s2=null) { // line 0
System.out.println(s1);
System.out.println(s2.length()); //Line 1
}
}
}
What i expected to happen was
a) s2 will be set to null because its an assignment operation as I am not using ==
b) And I will get a NPE at Line 1 during Runtime
and instead I got the following output as shown below.
Output is
if(s2=null)
^
required: boolean
found: String
1 error
Can someone explain why I am getting compile error ?
Java will not implicitly cast to a boolean like some languages will. You must put an expression that evaluates to a boolean inside of conditional:
if ((s2 = null) != null) { }
This condition of course makes no sense, but it's the equivalent of what you're attempting to do. It's worth noting by the way that assignments should rarely be done in a condition.
You should do like this:
if( (s2 = null) != null)
{
// do stuff
}
The reason you are getting this error because you have to explicitly put the code for boolean evaluation in conditions as Java doesn't implicitly cast it boolean.
The if condition evaluates only boolean conditions.
And the assignment operator does not give a boolean result here.
That is the reason for getting exception.
If you use if ((s2 = null) != null) instead of if(s2=null) it will work.
You should note the fact that in java there are only two boolean values : true and false unlike some other languages which use 0 as false and anything else as true .
Can someone explain why I am getting compile error ?
In an if statement the condition can either be true or false which are returned by comparison operations and by the boolean variables.
In,
if(s2=null)
the s2=null doesn't evaluate to any boolean value i.e, true or false therefore the compiler error :
required: boolean
found: String
An if-then statement is executed by first evaluating the Expression.
From, JLS - Chapter14 : Blocks and Statements
14.9.1. The if-then Statement
An if-then statement is executed by first evaluating the Expression.
If the result is of type Boolean, it is subject to unboxing
conversion (§5.1.8).
If evaluation of the Expression or the subsequent unboxing conversion
(if any) completes abruptly for some reason, the if-then statement
completes abruptly for the same reason.
Otherwise, execution continues by making a choice based on the
resulting value:
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.
Besides what everyone else said, s2 will never be null - you just assigned a new String to it! Are you sure you're not conflating string length/existence tests from other languages?
I am using Eclipse Helios IDE for our Web Application development.
Under Problems section in Eclipse, for some of lines the description is displayed as "Dead Code".
Could anybody please tell me what does Dead Code actually mean ?
Please see the screen shot for your reference.
For example this part is shown as dead code under Eclipse
else {
int length;
if (ar != null)
length = Array.getLength(ar);
else
length = 0; // This line is dead code
In Eclipse, "dead code" is code that will never be executed. Usually it's in a conditional branch that logically will never be entered.
A trivial example would be the following:
boolean x = true;
if (x) {
// do something
} else {
// this is dead code!
}
It's not an error, because it's still valid java, but it's a useful warning, especially if the logical conditions are complex, and where it may not be intuitively obvious that the code will never be executed.
In your specific example, Eclipse has calculated that ar will always be non-null, and so the else length = 0 branch will never be executed.
And yes, it's possible that Eclipse is wrong, but it's much more likely that it's not.
Dead code is code that will never be executed, e.g.
boolean b = true
if (!b) {
....
// dead code here
}
Dead code means, that there is no way that this code will be executed.
Sometimes you even can't compile it (like this case:)
private Boolean dead_code()
{
return true;
//Dead code below:
dosomething();
}
But in other cases this is not too obvious, eg this statement:
b=true;
[...]
if (b==false)
{
//Dead code
}
If you have this message, there is some major flaw in your code. You have to find it, otherwise your app won't work as intended.
There are two kinds of diagnostics that Eclipse gives out for marking code that will/may not be executed at runtime.
1) Unreachable code: These are the usual java warnings that follow the unreachability rules of the JLS, and are also given by javac. These are meant to be compile errors. Examples:
int foo() {
return 1;
int i = 1; // Unreachable
}
int foo2() {
while (true);
int i =1; //Unreachable
}
There are other more complicated examples :)
2) Dead code: This is Eclipse's own static analysis warnings, and are mostly tied out of the null analysis i.e.
void foo() {
Object o = null;
if (o == null) {
} else {
// dead code
}
The examples given above should NOT give a dead code warning. i.e.
boolean x = true;
if (x) {
// do something
} else {
// this is dead code!
}
should not give the warning, because JLS forbids the compiler to evaluate the 'value' of variables. All that we can evaluate is the 'nullness'
Hope this helps
You might be having an Null pointer exception in the lines above the "Dead Code" lines.
Make sure you check for "Null Pointer" exception.
It is possible that you have used the variable ar before. Then the compiler knows that the line in the else statement will never be executed. Either there will be a NullPointerException at the place where you used ar or the first part of the if statement will be executed.
let me give some answer for the dead code.
Eg:
public class UnreachableTest{
public static void main(){
try{
// some code
}
catch(Exception exc){
throw new NullPointerException();
System.out.println("Unreachable line"); // compile time error
}
}
}
here the System.out.println("Unreachable line"); is never executed.
Which in turn considered to be a dead code.
Another example may be:
int func(int i, int j)
{
int sum = i + j;
return i + j; // never actually using the sum
}
simple the function returns i + j; never really uses sum.
Sum is considered to be dead code here.
Some other case when this happens.
System.out.println("result :" + result + ":" + result.isEmpty());
if (result == null)
return result;
else if(!result.isEmpty())
str.append(result + " ");
1) Here as you you are printing result and checking isEmpty() eclipse assumes that result is not null so it will not go in if. So return result is dead code.
2)Now let say result is coming null so you will get NullPointerException in result.isEmpty() so again it will not go in if and return result is deadcode
To make this work just comment out System.out.println().
Eclipse gives this warning if the condition check you are giving may never be satisfied. Following are some examples
Object o=null;
if(o!=null) {
//Some code
}
Here Dead code warning will come as Object is already made null
Another example is given below
BSTTest bstTest=null;
bstTest.test=10;
if(bstTest==null) {
//some code
}
Here the code is trying to access a variable of the class. As the variable is already accessed, eclipse will give dead code warning in if(bstTest==null) as bstTest may not be null when the variable is already accessed.
Note: Here bstTest.test will give null pointer exception
Simple Example of Dead Code
public class IfTest {
public static void main(String[] args) {
if (true) {
if(false) {
System.out.println("a"); //Dead code, Never be Execute this if block.
}else {
System.out.println("b");
}
}
}
To simplify the term's Unreachable code and dead code:
Unreachable Code is a code block/statement in Java to which the control never reaches and never gets executed during the lifetime of the program. Following is the example of unreachable code. This generates compiler time error.
public void unreachableCodeExample() {
System.out.println("This will execute");
return;
System.out.println("This will not"); //This is Unreachable code
}
While A Dead code is an unreachable code, but it doesn’t generate compile time error. But if you execute it in eclipse (Or some other IDE) it gives you a warning. See below example,
public void deadCodeExample() {
if (true) {
System.out.println("This will execute");
return;
}
System.out.println("This will not"); //This is dead code
}
Dead code is the section of our code that is never going to execute runtime, its useless
EX:
if(false){ // statements }
For more example u can refer : DeadCode Examples
Try this:
while (true) {
if(false == true) break;
}
S.O.P("I will never reach here!") <-- This code will never be executed.
The code is valid as it conform to the compiler, however in reality the loop will never exit, and in effect S.O.P will never be executed.