Метод получения должен возвращать 'null' или выбрасывать исключение, если не может вернуть значение? [закрыто]
Проблема: Выбор подходящего способа обработки отсутствия объекта в методе Java
Я использую язык Java. У меня есть метод, который должен возвращать объект, если он найден.
В случае, если объект не найден, как лучше поступить?
- Вернуть
null
- Выбросить исключение
- Другой способ
Каков лучший подход или идиома в таких ситуациях?
5 ответ(ов)
Если вы всегда ожидаете найти значение, то в случае его отсутствия следует выбросить исключение. Исключение будет сигнализировать о том, что возникла проблема.
Если значение может отсутствовать или присутствовать, и оба варианта допустимы для логики приложения, то лучше возвращать null
.
Более важно: что делать в других частях кода? Консистентность — это важно.
В общем случае, бросайте исключения только в случае настоящих ошибок. Если отсутствие объекта является ожидаемым поведением, лучше возвращать null.
В остальном это вопрос личных предпочтений.
В общем, если метод всегда должен возвращать объект, то лучше использовать исключение. Если вы ожидаете возможность возврата null
и хотите обработать это определенным образом, выбирайте null
.
Что бы вы ни делали, настоятельно не рекомендую третий вариант: возвращать строку с сообщением "WTF".
Вопрос о том, как обрабатывать значения null
в коде, очень важен, и подход к этому действительно зависит от контекста. Вот несколько вариантов, как можно это организовать.
Если
null
никогда не указывает на ошибку, то просто возвращайтеnull
. В этом случае не возникает необходимости обрабатывать исключения, а вызов метода может выглядеть так:object o = FindObject();
Если
null
всегда указывает на ошибку, вам стоит выбрасывать исключение. Это явно сигнализирует о проблеме:object o = FindObject(); if (o == null) { throw new InvalidOperationException("Объект не найден."); }
Если
null
иногда является исключением, целесообразно создать две функции. Первая будет выбрасывать исключение, а вторая — выполнять проверку и возвращать результат через выходной параметр (например,out
). Если объект не найден, метод вернетfalse
, и вы сможете обрабатывать это без исключений:// Метод, который выбрасывает исключение object o = FindObject(); // будет санитарная проверка на null позже // Метод для безопасного поиска if (TryFindObject(out object o)) { // Делайте что-то с o } else { // o не найден }
Использование метода TryFindObject
с выходным параметром снижает вероятность ошибки при работе с null
, так как вы не забудете проверить его наличие, как это может произойти при прямом использовании метода, возвращающего null
.
Таким образом, выбор подхода зависит от ваших требований и логики программы.
Я хотел бы подытожить упомянутые ранее варианты и добавить к ним несколько новых:
- Возвращать null.
- Генерировать исключение.
- Использовать шаблон "нулевой объект".
- Предоставить булевый параметр в методе, чтобы вызывающий мог выбрать, хочет ли он, чтобы сгенерировалось исключение.
- Предоставить дополнительный параметр, чтобы вызывающий мог установить значение, которое будет возвращено, если нужное значение не найдено.
Также вы можете комбинировать эти варианты:
Предоставьте несколько перегруженных версий вашего метода получения объекта, чтобы вызывающий мог решить, какой подход ему подходит. В большинстве случаев только первая версия будет содержать реализацию алгоритма поиска, а остальные просто будут оборачивать первую:
Object findObjectOrNull(String key);
Object findObjectOrThrow(String key) throws SomeException;
Object findObjectOrCreate(String key, SomeClass dataNeededToCreateNewObject);
Object findObjectOrDefault(String key, Object defaultReturnValue);
Даже если вы решите предоставить только одну реализацию, вам может потребоваться использовать подобную соглашение об именовании, чтобы прояснить ваши обязательства. Это также поможет вам, если вы когда-либо решите добавить другие реализации.
Не стоит злоупотреблять этим подходом, но он может быть полезным, особенно при написании вспомогательного класса, который вы будете использовать в сотнях различных приложений с множеством различных конвенций обработки ошибок.
Как проверить, что в JUnit-тестах выбрасывается определенное исключение?
Как напечатать исключение в Python?
Mockito: Тестирование void метода, который выбрасывает исключение
Какова разница между `throw new Error` и `throw someObject`?
Java - MySQL: Не разрешено извлечение открытого ключа (Public Key Retrieval)