The tricky Java compiler 2.

jasy képe

The variable might not have been initialized

Each local variable and every blank final field must have a definitely assigned value when any access of its value occurs.
For this purpose the standard introduced the concepts of definitely assigned and definitely unassigned variables.
If a variable is definitely unassigned when it is used, a compiler error occurs.

In our following example the compiler says that the variable o might not have been initialized in the statement "if (o.equals(args))".
Of course it is true, there is no any execution where the else branch of the if statement will be executed because the condition is always true.

Example 1.
public static void main(String[] args)
{
  Object o;
  if ((true || ((o = args)==null) ) ^ false){
    ;
  } else {
    if (o.equals(args));
  }
}

The situation is very similar in the following case, which is semantically equivalent with the first one, but this code is compileable:

Example 2.
public static void main(String[] args)
{
 Object o;
  if ((true || ((o = args)==null)) == true){
    ;
  } else {
    if (o.equals(args));
  }
} 

If we change the right hand side of the equal operator with a method which returns true in every case, we got the same compiler error as in the first case:

Example 3.
public static void main(String[] args)
{
  Object o;
  if ((true || ((o = args)==null)) == methodWithReturnTrue()){
    ;
  } else {
    if (o.equals(args));
  }
} 

We do not have to worry, because the following code with the same semantic is compileable:

Example 4.
public static void main(String[] args)
{
  Object o;
  if ((true || ((o = args)==null)) | !methodWithReturnTrue()){
    ;
  } else {
    if (o.equals(args));
  }
} 

It is needless to say that the compilers behaviours do not follow the standard in these situations.
The standard categorizes the different types of binary operators into two groups to decide whether a variable is definitly [un]assigned after the execution of the given statements.
The first group contains the &&, ||, and ?: operators, while the second contains the remainders.
Altough the operators ==, |, ^ are in the same group, their behaviors are not the same. At least in the point of view of the compilation.

Prev