Альтернативы возвращению NULL - PullRequest
25 голосов
/ 12 мая 2011
   /**
     * Returns the foo with the matching id in this list
     * 
     * @param id the id of the foo to return
     * @return the foo with the matching id in this list
     */
    public Foo getFoo(int id)
    {
        for (Foo foo : list)
        {
            if (foo.getID() == id)
            {
                return foo;
            }
        }

        return null;
    }

Вместо возврата null, когда foo не найден, я должен throw exception?Имеет ли это значение, и есть ли идиома «лучших практик» по этому вопросу?Кстати, я знаю, что мой пример немного надуман, но я надеюсь, что вы поняли идею ...

Спасибо.

РЕДАКТИРОВАТЬ

Изменен код для получения Foo на основе id , чтобы лучше проиллюстрировать реальный сценарий.

Ответы [ 15 ]

1 голос
/ 12 мая 2011

Возвращение null вполне приемлемо.Я бы добавил еще пару десятков нажатий клавиш и задокументировал возможность возврата null в JavaDoc.

Бросок проверенного исключения означает, что вы должны пытаться / ловить или повторно выбрасывать это исключение везде, где вызывается ваш метод.Непроверенное исключение, особенно что-либо кроме NPE, может застать людей врасплох.

1 голос
/ 12 мая 2011

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

0 голосов
/ 22 февраля 2012

Хотя я согласен с тем, что кодирование для null - это простое и легкое шаблонное программирование, оно мало что дает для введенной сложности.Всегда предполагая, что ненулевые ссылки приводят к более чистой логике с немного меньшим количеством кода - вам все равно придется проверять наличие ошибок.

Аннотация выдержка ниже поможет вам не упасть на старые пути...

Используйте @ Nullable

Чтобы исключить NullPointerExceptions в вашей кодовой базе, вы должны быть дисциплинированы относительно нулевых ссылок.Мы добились успеха в этом, следуя и применяя простое правило:

Каждый параметр не равен нулю, если не указано явно.

Guava: Основные библиотеки Google дляJava и JSR-305 имеют простые API-интерфейсы для получения контроля над нулевыми значениями.Preconditions.checkNotNull может использоваться для быстрого сбоя, если найдена нулевая ссылка, и @Nullable может использоваться для аннотирования параметра, который допускает нулевое значение:

import static com.google.common.base.Preconditions.checkNotNull;
import static javax.annotation.Nullable;

public class Person {
  ...

  public Person(String firstName, String lastName, @Nullable Phone phone) {
    this.firstName = checkNotNull(firstName, "firstName");
    this.lastName = checkNotNull(lastName, "lastName");
    this.phone = phone;
  }

Если нулевой уровень допустим для вашего классаВы можете аннотировать поле или параметр с помощью @Nullable ... используя любую аннотацию @Nullable, например, edu.umd.cs.findbugs.annotations.Nullable или javax.annotation.Nullable.

0 голосов
/ 03 июля 2011

Другая точка зрения, которую я не читал в других ответах, заключается в следующем:

Содержит ли list null из Foo?Если это так, никто не узнает, был ли найден идентификатор или был ли он связан с null.В этом случае:

  • Создать исключение, что список не найден;
  • Обернуть результат в другой объект (например, SearchResult, который сообщает вам, был ли найден объект), это ассоциативный идентификатор, это результат или нет результата, если он не был найден);
  • Создайте метод existsFoo(int id).

У каждого решения есть свои проблемы, и это зависитна случай, который нужно использовать:

  • Как уже отмечалось, Exception s исключительные ;
  • Обертка, SearchResult, должна быть выделенакаждый раз, когда вы хотите повторить поиск.Обёртка может быть сделана изменяемой , но это создает много новых трудностей и проблем;
  • existsFoo должен искать в списке, что удваивает стоимость знания, существует ли ключ или нет.

Обычно я могу сказать:

  • Является ли ID не найденным исключительным?Используйте IllegalArgumentException;
  • Передается ли результат другим классам, используемым как объект?Использовать обертку, например, SearchResult;
  • Проверяется ли с getFoo только, является ли он нулевым или нет (существует или нет)?Используйте другой метод, existsFoo.
0 голосов
/ 13 мая 2011

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

  1. Если вы ожидаете, что результат "не найден" будет происходить достаточно часто, чтобы он мог негативно повлиять на производительность *, тогдаверните значение null и проверьте его в вызывающей программе.
  2. Если результаты "not found" будут относительно редкими или приведут к тому, что ваше приложение отклонит запрос, то возникнет исключение.Исключения могут сделать ваш код более легким для чтения, поскольку вы можете гарантировать, что успешный возврат приведет к созданию объекта, поэтому вам не нужно проверять его на нуль.

Я согласен с мнением, что исключенияследует использовать для исключительных условий, что является расширенным набором условий ошибки.Я также принял предпочтение Spring / Hibernate для непроверенных исключений, что позволяет избежать обременительной логики try / catch.

* При использовании исключений и возврате null не слишком много накладных расходов.Я только что сделал быстрый тест, требуется 4 мс для вызова метода миллион раз, который возвращает ноль, и только 535 мсек для другого метода миллион раз, который выдает исключение.

...