Странное предупреждение компилятора Java: неверное «предупреждение о возможном нулевом доступе» - PullRequest
2 голосов
/ 21 июля 2011

(JDK 1.6.0_23, Eclipse 3.7.0 с уровнем предупреждения «Доступ к нулевому указателю» в «Предупреждение»). Рассмотрим следующий пример кода:

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

В последней строке я получаю следующее предупреждение: Potential null pointer access: The variable obj may be null at this location. Есть ли реальный способ для obj быть на самом деле null или почему так считает компилятор?

Ответы [ 5 ]

8 голосов
/ 21 июля 2011

Я бы сказал, что компилятор видит это следующим образом:

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

Так что obj.toString () может быть нулевым, если вы не можете интерпретировать, что делает цикл.

Например, вы можетеобмануть компилятор, заменив:

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

на

void x(int x){
    if(true) return;
    x++;  //compiles
}
4 голосов
/ 21 июля 2011

Кажется, что компилятор не может хорошо анализировать код.На самом деле он не может «запустить» его и понять, что ваш оператор if предотвращает нулевой доступ.Я немного поиграл с кодом и нашел следующую эквивалентную версию, которая не выдает предупреждение:

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

Да, я знаю, что эта версия выполняет 2 проверки на ноль на каждой итерации цикла вместо одной.Таким образом, вы можете изменить свой код, добавить @SuppressWarning к своему коду или удалить Thread.sleep(25)

3 голосов
/ 21 июля 2011

Это улучшенная версия кода AlexR, которая, на мой взгляд, является хорошим решением проблемы, одновременно улучшая читабельность кода.Моя версия имеет вторую строку obj = getObject();, но не нуждается во второй проверке, поэтому в целом она должна быть более производительной.

Object obj = null;
obj = getObject();
while (obj == null) {
    Thread.sleep(25);
    obj = getObject();
}
obj.toString();
3 голосов
/ 21 июля 2011

Компилятор видит в этом потенциал того, что объект не будет инициализирован. На самом деле невозможно увидеть, что условие разрыва цикла состоит в том, что объект не равен нулю, или он будет работать вечно или до тех пор, пока не перестанет быть нулевым. Я получаю только предупреждение на JDK, который вы упомянули. При использовании более обновленной версии это предупреждение не появляется.

0 голосов
/ 30 августа 2013

Я знаю, что это старая тема, но как насчет этого?Я нахожу это более читабельным, чем версии Koraktor и AlexR.

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

Но в моем коде я обычно включил «Включить« assert »в нулевой анализ» в настройках компилятора eclipse и добавил assert.Поэтому мне не нужно менять поток управления и в то же время избегать предупреждения:

Object obj = null;    
while (true) {
    obj = getObject();
    if (obj != null) break;
    Thread.sleep(25);
}
assert obj!=null;
obj.toString();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...