5

Метод получения должен возвращать 'null' или выбрасывать исключение, если не может вернуть значение? [закрыто]

12

Проблема: Выбор подходящего способа обработки отсутствия объекта в методе Java

Я использую язык Java. У меня есть метод, который должен возвращать объект, если он найден.

В случае, если объект не найден, как лучше поступить?

  1. Вернуть null
  2. Выбросить исключение
  3. Другой способ

Каков лучший подход или идиома в таких ситуациях?

5 ответ(ов)

5

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

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

Более важно: что делать в других частях кода? Консистентность — это важно.

1

В общем случае, бросайте исключения только в случае настоящих ошибок. Если отсутствие объекта является ожидаемым поведением, лучше возвращать null.

В остальном это вопрос личных предпочтений.

0

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

Что бы вы ни делали, настоятельно не рекомендую третий вариант: возвращать строку с сообщением "WTF".

0

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

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

    object o = FindObject();
    
  2. Если null всегда указывает на ошибку, вам стоит выбрасывать исключение. Это явно сигнализирует о проблеме:

    object o = FindObject();
    if (o == null)
    {
        throw new InvalidOperationException("Объект не найден.");
    }
    
  3. Если null иногда является исключением, целесообразно создать две функции. Первая будет выбрасывать исключение, а вторая — выполнять проверку и возвращать результат через выходной параметр (например, out). Если объект не найден, метод вернет false, и вы сможете обрабатывать это без исключений:

    // Метод, который выбрасывает исключение
    object o = FindObject(); // будет санитарная проверка на null позже
    
    // Метод для безопасного поиска
    if (TryFindObject(out object o))
    {
        // Делайте что-то с o
    }
    else
    {
        // o не найден
    }
    

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

Таким образом, выбор подхода зависит от ваших требований и логики программы.

0

Я хотел бы подытожить упомянутые ранее варианты и добавить к ним несколько новых:

  1. Возвращать null.
  2. Генерировать исключение.
  3. Использовать шаблон "нулевой объект".
  4. Предоставить булевый параметр в методе, чтобы вызывающий мог выбрать, хочет ли он, чтобы сгенерировалось исключение.
  5. Предоставить дополнительный параметр, чтобы вызывающий мог установить значение, которое будет возвращено, если нужное значение не найдено.

Также вы можете комбинировать эти варианты:

Предоставьте несколько перегруженных версий вашего метода получения объекта, чтобы вызывающий мог решить, какой подход ему подходит. В большинстве случаев только первая версия будет содержать реализацию алгоритма поиска, а остальные просто будут оборачивать первую:

Object findObjectOrNull(String key);
Object findObjectOrThrow(String key) throws SomeException;
Object findObjectOrCreate(String key, SomeClass dataNeededToCreateNewObject);
Object findObjectOrDefault(String key, Object defaultReturnValue);

Даже если вы решите предоставить только одну реализацию, вам может потребоваться использовать подобную соглашение об именовании, чтобы прояснить ваши обязательства. Это также поможет вам, если вы когда-либо решите добавить другие реализации.

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

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь