Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Behaviour Difference: 'null' initialized final static member, and 'null' initialized final local variable

I came across a behavior, I didn't knew of earlier, in the follow up code.

Consider the 1st case:

public static void main(String[] args) {    
    final String str = null;
    System.out.println(str.length());  // Compiler Warning: NullPointerAccess
}

As expected, the compiler shows me following warning on str being null - Null pointer access: The variable str can only be null at this location.

Now, when I moved that variable a static final field initialized to null:

class Demo {
    static final String str = null;

    public static void main(String[] args) {
        System.out.println(str.length());  // No Compiler Warning
    }
}

Now, compiler doesn't show any warning. AFAIK, Compiler should know that str being final, will not change its value, at any point of the code. And given that it is null, will definitely result in NullPointerException later on, which it does.

Although, compiler successfully warns me of this in the first case, why it cannot identify this in the 2nd case. Why this change of behaviour? The behaviour is same, if I change static field to instance field, and access it using an instance of Demo.

I thought this behaviour might have been specified in JLS, so I went through the topic Definite Assignment, but didn't find anything related to this issue. Can anyone explain the change in behaviour? I'm looking for some strong point with some link to JLS if possible?

Apart from that, why compiler shows me only warning in the first place, as I think for the same reason I stated above, the method invocation will definitely throw NPE at runtime, since the field can't be changed? Why didn't it rather show me a Compiler Error? Am I expecting too much from compiler, as it seems to be quite obvious, that the runtime result of str.length() can't be anything than NPE?


Sorry for missing that earlier:

I'm using Eclipse Juno, on Ubuntu 12.04 with OpenJDK 7.

like image 794
Rohit Jain Avatar asked Aug 02 '13 13:08

Rohit Jain


People also ask

What is the difference between static and final variable in Java?

The static keyword means the value is the same for every instance of the class. The final keyword means once the variable is assigned a value it can never be changed. The combination of static final in Java is how to create a constant value.

Can a final string be null?

AFAIK, Compiler should know that str being final, will not change its value, at any point of the code. And given that it is null , will definitely result in NullPointerException later on, which it does.

Will static block be executed with final variable?

We can initialize a final static variable at the time of declaration. Initialize inside a static block : We can also initialize a final static variable inside a static block because we should initialize a final static variable before class and we know that static block is executed before main() method.

When can final local variables be initialized?

Initializing a final Variable You can initialize a final variable when it is declared. This approach is the most common. A final variable is called a blank final variable if it is not initialized while declaration. Below are the two ways to initialize a blank final variable.


2 Answers

I am not sure in 100%, but in the second case where you have final field against local variable, there is possible assigns to this final field some value direct in static (or instance block depending if variable is static or not) initialization block:

class Demo {
...
static {
 str = "some text";
}
...
}

so compiler don't give you warn.

like image 81
michal Avatar answered Oct 10 '22 19:10

michal


Wow! It turned out, it was eclipse specific issue. When I compiled the code using:

javac -Xlint:all Demo.java

it didn't show any warning for any case. So, I went back to eclipse to check any settings enabled for this case, and found one.

In Windows -> Preferences -> Java -> Compiler -> Errors/Warnings, under Null Analysis, I can change the way the Null Pointer Access should be treated by Eclipse Compiler. I can set it to - Ignore, Error, or Warning.

And now it seems like a completely silly question. Shame on me. :(

like image 28
Rohit Jain Avatar answered Oct 10 '22 17:10

Rohit Jain