Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 247
uml Avatar asked Oct 17 '12 14:10

uml


People also ask

What are the three types of branching?

There are three types of supporting branches with different intended purposes: feature, release, and hotfix.

What are different types of branching statements in C?

Common branching statements include break , continue , return , and goto .

What is an example of conditional branching?

In this example, there are only two branches. The first branch, which selects a loan offer from United Loan, is executed if a case condition containing an XPath Boolean expression is met. Otherwise, the second branch, which selects the Star Loan loan offer, is executed.


2 Answers

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);
}
like image 55
Sergey Kalinichenko Avatar answered Sep 30 '22 00:09

Sergey Kalinichenko


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.

like image 28
Stephen C Avatar answered Sep 29 '22 22:09

Stephen C