Why Java identifies unreachable code only in case of while loop? [duplicate] - java

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) {
...
}

Related

Why does compiler build return unreachable code in some cases

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.

Why does a String need to be initialized even if the assignment will happen later?

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.

Unreachable code while loop

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.

using { } after semicolon [duplicate]

This question already has answers here:
Anonymous code blocks in Java
(11 answers)
Closed 9 years ago.
In an example of android code given in a book regarding action bar, the sample given is as the following:
MenuItem menu1 = menu.add(0, 0, 0, "Item 1");
{
menu1.setIcon(R.drawable.ic_launcher);
menu1.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
How is using curly braces after a semi-colon possible? There is clearly some concept that I do not understand right here.
They are completely optional in this case and have no side-effect at all. In your example it sole serves to purpose of making the code more readable by intending the property assignment which belong to the control. You could as well do it without the braces. But if you'd use a tool to reformat your code, the indentation is likely gone.
However, if you have a Method and you put {} in there, you can create a new variable scope:
void someMethod() {
{
int x = 1;
}
// no x defined here
{
// no x here, so we may define a new one
string x = "Hello";
}
}
You can start a new scope anywhere in a Method where you can start a statement (a variable declaration, a method call, a loop etc.)
Note: When you have for example an if-statement you also create a new variable scope with that braces.
void someMethod() {
if (someThing) {
int x = 1;
}
// no x defined here
if (somethingElse) {
// no x here, so we may define a new one
string x = "Hello";
}
}
The same is true for while, for, try, catch and so on. If you think about it even the braces of a method body work in that way: they create a new scope, which is a "layer" on top of the class-scope.
It's called anonymous code blocks, they are supposed to restrict the variable scope.
Those are Initialization Blocks.
I don't think this is the correct usage of initialization block.
Apart from the example you have produced, these blocks are just used for initialization purpose. Click Here for detailed view.

what does Dead Code mean under Eclipse IDE Problems Section

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.

Categories

Resources