Оценка короткого замыкания Java - PullRequest
17 голосов
/ 30 ноября 2009

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

if( (perfectAgent != null) && (perfectAgent.getAddress().equals(entry.getKey())) ) {

В этом случае perfectAgent равно null, поэтому я просто хочу, чтобы все выражение возвращало false, но мое приложение по-прежнему падает на этой строке с исключением NullPointerException.

РЕДАКТИРОВАТЬ, общий ответ:

Поскольку perfectAgent равно null, ничего справа от && не должно выполняться, поскольку выражение не может быть истинным. Более того, невозможно выполнить perfectAgent.getAddress(), так как perfectAgent не содержит допустимой ссылки (это ноль и все). Я пытаюсь использовать оценку короткого замыкания, чтобы не проверять нулевое значение в отдельном утверждении, поскольку это делает логику более небрежной.

РЕДАКТИРОВАТЬ 2 (или, я идиот): Да, как и во многих вещах в жизни, вы выясняете ответ сразу после объявления миру, что вы идиот. В этом случае я отключил автоматическое построение Eclipse, когда делал что-то еще, и не включил его снова, поэтому я отлаживал файлы классов, которые не совпадали с моим источником.

Ответы [ 7 ]

10 голосов
/ 30 ноября 2009

Если perfectAgent действительно равно нулю, этот код не будет генерировать исключение (по крайней мере, если предположить, что не происходит странных потоковых операций, изменяя его с ненулевого на нулевое значение в середине выражение). Я был бы очень шокирован, если бы вы могли создать короткую, но полную программу, демонстрирующую это.

Так что да, ваша интуиция права - это не должно быть проблемой. Ищите в другом месте причину. Я сильно подозреваю, что perfectAgent не является на самом деле нулевым, и вы сталкиваетесь с любой другой ситуацией в этом коде, которая может вызвать исключение.

Я предлагаю вам попытаться извлечь этот фрагмент кода в короткий, но полный пример - если вы сможете это сделать, я съем свою метафорическую шляпу; в противном случае вы, вероятно, найдете проблему при попытке извлечения.

С чего вы взяли, что perfectAgent на самом деле равно нулю? Попробуйте вставить этот код перед ним:

if (perfectAgent == null)
{
    System.out.println("Yup, it's null");
}

Другая очень, очень тонкая возможность заключается в том, что вы столкнулись с ошибкой JIT - но я в этом сильно сомневаюсь.

7 голосов
/ 30 ноября 2009

Java имеет оценку короткого замыкания. Возможно, entry - это null, поэтому entry.getKey() вызывает NullPointerException. Другая возможность состоит в том, что getAddress() либо возвращает null, либо имеет внутри себя NullPointerException (если это сложнее, чем простой оператор return).

РЕДАКТИРОВАТЬ: я вижу ваши правки, где вы утверждаете это:

Более того, невозможно выполнить perfectAgent.getAddress() ...

Но что, если perfectAgent.getAddress() будет успешно выполнено и вернет null? Видишь, что я имею в виду ...

6 голосов
/ 30 ноября 2009

Урок расширенной отладки № 1:

Если вы столкнулись с кажущейся невозможной ошибкой (например, той, которая противоречит вашим знаниям о Java), сделайте следующее:

  • Обратитесь к авторитетному учебнику (или, что еще лучше, к соответствующему стандарту), чтобы подтвердить, что ваше понимание не ошибочно. (В этом случае ваше понимание было правильным, и любой полуприличный учебник подтвердит это через минуту.)

  • Проверьте все глупости, которые вы могли бы сделать, что могло привести к невозможной ошибке. Такие вещи, как не сохранять файл, не делать полную сборку, запускать старую / устаревшую версию приложения, находиться в неправильном каталоге и т. Д.

Таким образом, научитесь сомневаться в себе немного больше.

2 голосов
/ 30 ноября 2009

Вы гарантируете, что perfectAgent не равно нулю, поэтому один или несколько из perfectAgent.getAddress() или entry или entry.getKey() должны быть равны нулю. Или getAddress () или getKey () попадают в NPE в своей реализации.

Для отладки такого рода вещей сначала посмотрите на трассировку стека, чтобы определить местоположение. Это скажет вам, происходит ли это в getAddress () или в getKey (), или в фрагменте вставленного кода, который их вызывает. Затем, если он находится в этом фрагменте, добавьте некоторый код перед проверкой if, который является нулевым. Вы можете использовать старый добрый System.err.println () или утверждений . (Если вы используете утверждения, обязательно включите их с флагом -enableassertions команды java.)

Обновление: Таким образом, моя интерпретация оказалась неверной ... проблема представила два противоречивых факта (на этой линии был NPE и все же должно было произойти короткое замыкание), и я автоматически предположил первый факт был верным, а второй - ложным, когда фактически это была совершенно другая проблема из-за отключения автоматической сборки в Eclipse. Duh! При отладке чего-то «невозможного» это помогает радикально скептически относиться.

1 голос
/ 30 ноября 2009

Большая тайна. Я скопировал вашу строку кода и протестировал perfectAgent == null, entry == null, entry.getKey() == null и их комбинации: в моем тестовом стенде нет NPE (Java 1.6)

Какая бы это ни была досадная ошибка, я сомневаюсь, что это как-то связано с оценкой короткого замыкания. Если эта строка вызывает NPE, то, насколько я могу сказать, perfectAgent не равен нулю. Удачи и - покажите нам ошибку, как только вы ее поймали:)

1 голос
/ 30 ноября 2009

Есть три ссылки, отличные от perfectAgent, которые могут быть нулевыми:

  • perfectAgent.getAddress ()
  • запись
  • entry.getKey ()

Разбейте оператор или запустите его в отладчике.

0 голосов
/ 30 ноября 2009

Попробуйте отформатировать код следующим образом:

if( 
  (perfectAgent != null) 
  && (
      perfectAgent.getAddress()
      .equals(
       entry.getKey()
      )
     ) 
  ) {

Это должно дать вам лучшую запись строки трассировки стека.

...