简体   繁体   中英

Strange Java compiler warning: incorrect “potential null access warning”

(JDK 1.6.0_23, Eclipse 3.7.0 with "Potential null pointer access" warning level at "Warning") Consider the following example code:

Object obj = null;
for (;;) {
    obj = getObject();
    if (obj != null) break;
    Thread.sleep(25);
}
obj.toString();

I'm getting the following warning on the last line: Potential null pointer access: The variable obj may be null at this location . Is there any real way for obj to actually be null or why the compiler thinks so?

I'd say the compiler sees this as:

Object obj = null;
[Too dumb to interpret this loop]
obj.toString();

So obj.toString() could be null if you cannot interpret what the loop does.

For example you can trick the compiler by replacing:

void x(int x){
    return;  
    x++;  //error unreachable code
}

with

void x(int x){
    if(true) return;
    x++;  //compiles
}

It seems that compiler cannot analyze the code very well. It actually cannot "run" it and understand that your if statement prevents null access. I played a little bit with the code and found the following equivalent version that does not produce warning:

    Object obj = null;
    do {
        obj = getObject();
        if (obj == null) {
            Thread.sleep(25);
        }
    } while (obj == null);
    obj.toString();

Yes, I know that this version performs 2 null checks on each loop iteration instead of one. So, it is up to you to change your code, add @SuppressWarning to your code or to remove Thread.sleep(25)

The compiler is seeing this as a potential that the object will not be initialized. It is not really able to see that the loop breaking condition is that the object is not null or it will just run forever or until it is no longer null. I only get the warning on the JDK you mentioned. Using a more updated version this warning does not appear.

This is an improved version of AlexR's code which I think is a nice solution to the problem while also improving readability of the code. My version features a second obj = getObject(); line, but doesn't need the second check, so it should be more performant overall.

Object obj = null;
obj = getObject();
while (obj == null) {
    Thread.sleep(25);
    obj = getObject();
}
obj.toString();

I know it's an old thread, but how about this? I find it more readable than the versions of Koraktor and AlexR.

Object obj = null;
for (obj=getObject(); obj==null; obj=getObject()) {
  Thread.sleep(25);
}
obj.toString();

But in my code, I usually have enabled "Include 'assert' in null analysis" in eclipse compiler settings and add an assert. So I don't have to change control flow and at the same time avoid the warning:

Object obj = null;    
while (true) {
    obj = getObject();
    if (obj != null) break;
    Thread.sleep(25);
}
assert obj!=null;
obj.toString();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM