Найкращий спосіб перевірити нульові значення в Java?

Перш ніж викликати функцію об'єкта, мені потрібно перевірити, чи є об'єкт нульовим, щоб уникнути викидання NullPointerException .

What is the best way to go about this? I've considered these methods.
Which one is the best programming practice for Java?

// Method 1
if (foo != null) {
    if (foo.bar()) {
        etc...
    }
}

// Method 2
if (foo != null ? foo.bar() : false) {
    etc...
}

// Method 3
try {
    if (foo.bar()) {
        etc...
    }
} catch (NullPointerException e) {
}

// Method 4 -- Would this work, or would it still call foo.bar()?
if (foo != null && foo.bar()) {
    etc...
}
25
Залежно від вашого випадку використання, також може бути сенс заборонити значення null для foo та викинути NullPointerException , якщо null foo передається вашому методу.
додано Автор assylias, джерело
@NickFreeman я не погоджуюсь - див., Наприклад: stackoverflow.com/a/8196334/829571 - стандарт (в JDK, в гуаві і відповідно до Ефективної Java) - це викинути NPE. Хоча, звичайно, IAE також широко використовується в таких ситуаціях.
додано Автор assylias, джерело
Ніколи не допускати винятків із нульовим вказівником. Він потрапляє до категорії "Винятки з головою" blogs.msdn.com/b/ericlippert/archive/2008/09/10/…
додано Автор Nick Freeman, джерело
1) Різниця між 1 і 4 - вибір стилю та мікро-оптимізація в кращому випадку. 2) Це не має значення, доки ви не дозволяєте виключити виключення, а не турбує про те, що краще всього використовувати, час буде краще витрачатись на чіткі алгоритми дизайну/краще.
додано Автор Nick Freeman, джерело
@assylias У цьому випадку слід використати IllegalArgumentException .
додано Автор Nick Freeman, джерело
Вибачте за стільки коментарів. Ще однією концепцією, яку потрібно вивчити, буде Null Object Pattern - en.wikipedia.org/wiki/Null_Object_pattern
додано Автор Nick Freeman, джерело
@NickFreeman Я так думав, я просто додав, що для наочності, спасибі за пояснення чому, хоча
додано Автор Arty-fishL, джерело

16 Відповіді

Найкращий спосіб 4:

if(foo != null && foo.bar()) {
   someStuff();
}

буде використовувати оцінку короткого замикання , тобто він закінчується, якщо перша умова логічного AND невірно.

53
додано
+1, щоб пояснити, чому це найкраще
додано Автор robjohncox, джерело
Спасибі, я думав, що це буде найкращим, але я не знав, чому це не буде називати другою умовою, або іноді це може - дякую, пояснивши, чому.
додано Автор Arty-fishL, джерело

The last and the best one. i.e LOGICAL AND

  if (foo != null && foo.bar()) {
    etc...
}

Because in logical &&

Не треба знати, що з правого боку, результат має бути хибним

Prefer to read :Java logical operator short-circuiting

11
додано

У Java 8 найкращим способом перевірки на нуль є:

Objects.isNull(obj) //returns true if the object is null

Objects.nonNull(obj) //returns true if object is not-null

if(Objects.nonNull(foo) && foo.something())//Uses short-circuit as well. No Null-pointer Exceptions are thrown.

Крім цього ... Ви також можете зайти з факультативного класу Гуави

Знижує типологічні помилки, такі як (obj = null) , які завжди повертають true , як обговорюється в попередніх відповідях.

6
додано
  • Не заводьте NullPointerException . Це погана практика. Краще переконатися, що значення не є нульовим.
  • Метод №4 буде працювати для вас. Це не буде оцінювати другу умову, оскільки Java має коротке замикання (тобто наступні умови не будуть оцінюватися, якщо вони не змінюють кінцевий результат логічного виразу). У цьому випадку, якщо перший вираз логічного AND оцінює false, подальші вирази не потрібно оцінювати.
5
додано
@RichardTingle винятки не такі дорогі, як вони були (особливо, якщо вам не потрібно перевіряти слід стека). Крім того, я погоджуюсь - причина для мене, однак, полягає в тому, що винятки порушують поточний потік програми, як того очікує читач.
додано Автор Thorbjørn Ravn Andersen, джерело
Варто зазначити, чому ловлення винятків з нульовим вказівником є ​​поганою практикою; Винятки дійсно дуже дорогі, навіть деякі з них дійсно сповільнять ваш код
додано Автор Richard Tingle, джерело
@josefx Вартість виконання (майже) що-небудь одного разу незначна, вона, очевидно, має значення лише тоді, коли розділ коду в ньому є горловиною пляшки; однак, якщо це тоді, то це може стати причиною. Я зібрав деякі дані у відповідь на це питання stackoverflow.com/questions/16320014/… . Очевидно, що це також погана ідея з причин, про які ви згадуєте (крім багатьох інших). Можливо, я мав би сказати "одну з причин", а не "причину"
додано Автор Richard Tingle, джерело
@RichardTingle в більшості випадків вартість винятку є незрозумілою (java використовує їх всюди), більше того, NullpointerException може походити не тільки з foo, але і в будь-якому місці між try {and} catch, тому ви можете сховати помилку шляхом лову
додано Автор josefx, джерело

Метод 4 є далеко не найкращим, оскільки він чітко вказує, що станеться, і використовує мінімум коду.

Метод 3 просто неправильний на кожному рівні. Ви знаєте, що елемент може бути нульовим, тому це не виняткова ситуація, це те, що ви повинні перевірити.

Метод 2 просто робить його складнішим, ніж це потрібно.

Метод 1 - це лише метод 4 з додатковою лінією коду.

4
додано

Я б сказав, що метод 4 є найбільш загальним ідіомом із коду, який я переглянув. Але це завжди відчуває себе трохи смердючою для мене. Припускається, що foo == null - це те саме, що foo.bar() == false.

Це не завжди відчуваєш право на мене.

2
додано

Method 4 is my preferred method. The short circuit of the && operator makes the code the most readable. Method 3, Catching NullPointerException, is frowned upon most of the time when a simple null check would suffice.

2
додано

У Java 7 можна використовувати Objects.requireNonNull() . Додайте імпорт класу Objects з java.util .

public class FooClass {
    //...
    public void acceptFoo(Foo obj) {
        //If obj is null, NPE is thrown
        Objects.requireNonNull(obj).bar(); //or better requireNonNull(obj, "obj is null");
    }
    //...
}
2
додано
У випадку Java 8 ви можете спробувати використовувати клас Необов'язковий .
додано Автор KrishPrabakar, джерело
Якось SO не дозволяє мені додати до коду рядок import java.util.Objects; , тому розміщуйте його в коментарях тут.
додано Автор KrishPrabakar, джерело
Закине NullPointer, якщо він буде Null
додано Автор ScriptKiddy, джерело

If you control the API being called, consider using Guava's Optional class

More info here. Change your method to return an Optional instead of a Boolean.

This informs the calling code that it must account for the possibility of null, by calling one of the handy methods in Optional

1
додано

Як інші сказали, # 4 найкращий спосіб, коли не використовує метод бібліотеки. Однак ви завжди повинні поміщати нуль у лівій частині порівняння, щоб ви випадково не призначили null для foo у випадку помилки. У такому випадку компілятор буде ловити помилку.

// You meant to do this
if(foo != null){

// But you made a typo like this which will always evaluate to true
if(foo = null)

// Do the comparison in this way
if(null != foo)

// So if you make the mistake in this way the compiler will catch it
if(null = foo){

// obviously the typo is less obvious when doing an equality comparison but it's a good habit either way
if(foo == null){
if(foo =  null){
1
додано

Простий рядок коду, щоб перевірити нуль:

namVar == null ? codTdoForNul() : codTdoForFul();
0
додано

Ви також можете використовувати StringUtils.isNoneEmpty ("") для перевірки є нульовим або порожнім.

0
додано

Ваша остання пропозиція найкраща.

if (foo != null && foo.bar()) {
    etc...
}

Оскільки:

  1. Це легше читати.
  2. Це безпечно: foo.bar() ніколи не буде виконано, якщо foo == null.
  3. Запобігає поганій практиці, такою як ловлення NullPointerExceptions (в основному через помилку у вашому коді)
  4. Він повинен виконуватися так швидко або навіть швидше, ніж інші методи (навіть якщо я вважаю, що це майже неможливо це помітити).
0
додано

якщо у вас немає доступу до загальної бібліотеки apache, можливо, це буде добре

if(null != foo && foo.bar()) {
//do something
}
0
додано
, якщо у вас немає доступу до загальної бібліотеки apache , яку частину бібліотеки ви мали на увазі?
додано Автор Maksim, джерело
Другий фрагмент кидає NPE, коли foo є нульовим.
додано Автор Xaerxess, джерело
Xaerxess, ви маєте рацію, я вилучив фрагмент коду з можливим NPE
додано Автор Cyril Deba, джерело

Якщо взагалі ви збираєтеся перевірити з подвійним рівним "==", то перевірте нуль з об'єктом ref як

if(null == obj) 

замість

if(obj == null)

тому що, якщо ви помиляєтеся, єдиний рівний, якщо (obj = null) він повернеться істинно (присвоєння об'єкту повертає успіх (який є "true" у значенні).

0
додано

Ми можемо використовувати статичний метод Object.requireNonNull класу Object. Втілення наведено нижче

public void someMethod(SomeClass obj) {
    Objects.requireNonNull(obj, "Validation error, obj cannot be null");
}
0
додано
ІТ КПІ - Java
ІТ КПІ - Java
436 учасників