uml
uml

Reputation: 1189

Branching which can't be seen by compiler

This is the snippet of code in Java language:

 public void name(){
int value = 9;
 int o;
if(value > 9)
 o = 5;

if(value <= 9)
o = 8;

System.out.println(o);
}

Why does compiler can't see the second if statement considering the last option of the value? It won't compile. Best regards

Upvotes: 5

Views: 116

Answers (5)

Stephen C
Stephen C

Reputation: 718986

The reason that the original version doesn't compile is that the JLS' "definite assignment" rules in JLS section 16 say that o has not been definitely assigned. The compiler reports this with an enigmatic message that says that "o may not have been initialized".

Now, anyone with simple deductive skills can see that the 2nd if condition is the negation of the 1st if condition, and therefore the variable will in fact always be initialized. However, the JLS does not allow a compiler to make that deduction. The JLS says this an error ...

There are a number of ways to fix this. For example

  • Assign something to o in the declaration.
  • Replace the two if statements with a single if / else statement.
  • Declare value as final.

The last fix is interesting. The reason it works is that the JLS definite assignment rules require the compiler to take the value of a compile-time constant boolean-valued expression into account.

This statement (with the final added)

    final int value = 9;

means that value is a compile-time constant. That means that value <= 9 and value > 9 are also compile-time constants. The JLS definite assignment rules therefore state that o is definitely assigned after

    if(value <= 9) o = 8;

and can be used later without a compilation error.


The definite assignment rules are designed to prevent the use of uninitialized variables, and prevent blank final variables being initialized more than once.

The JLS's conservative treatment of expression values in the definite assignment rules is designed to avoid problems where one Java compiler deduces that something is definitely assigned, but another cannot. The subcase of compile-time-constant expressions can be handled by simply evaluating the expression, and the JLS rules implicitly recognize this.

Upvotes: 1

pingw33n
pingw33n

Reputation: 12510

As per JLS (§16) every local variable and non-blank field must be definitely assigned before it can be used. The compiler does some basic static analysis to ensure it.

The idea behind definite assignment is that an assignment to the local variable or blank final field must occur on every possible execution path to the access. Similarly, the idea behind definite unassignment is that no other assignment to the blank final variable is permitted to occur on any possible execution path to an assignment.

The static analyzer can only deduce values of constant expressions ($15.28) which is not the case in your example.

Upvotes: 0

codeMagic
codeMagic

Reputation: 44571

Initialize o before if statements after you declare it

o=0;

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726699

The compiler must treat value as changeable unless you say otherwise. Declaring it final fixes the problem:

public void name(){
    final int value = 9;
    int o;
    if(value > 9) o = 5;
    if(value <= 9) o = 8;
    System.out.println(o);
}

Upvotes: 5

Sashi Kant
Sashi Kant

Reputation: 13465

During the compilation:

The compiler sees that you haven't initialized the variable 'o' and you are printing in the sysout.

you can achieve this :

public void name(){
int value = 9;
 int o;
if(value > 9)
 o = 5;

else
o = 8;

System.out.println(o);
}

Upvotes: 0

Related Questions