JavaRush /Java блог /Архив info.javarush /Возвращайте массив нулевой длины, а не null
alexnjc
31 уровень

Возвращайте массив нулевой длины, а не null

Статья из группы Архив info.javarush
Нередко встречаются методы, имеющие следующий вид:

private List cheesesInStock = … ;
/**
* @return массив, содержащий все сыры, имеющиеся в магазине,
* или null, если сыров для продажи нет.
*/
public Cheese[] getCheeses() {
if (cheesesInStock.size() == 0)
return null;
}
Нет причин рассматривать как особый случай ситуацию, когда в продаже нет сыра. Это требует от клиента написания дополнительного кода для обработки возвращаемого методом значения пull, например:

Cheese[] cheeses = shop.getCheeses();
if (cheeses ! = пull &&
Аrrауs.аsList(shор.gеtСhееsеs()).соntаins(Сhееsе.SТILТON))
Sуstеm.оut.рrintln("Jоllу good, just the thing.");
вместо простого:

if  (Аrrаys.аsList(shор.gеtСhееsеs()).соntаins(Сhееsе.SТILTON)) Sуstеm.оut.рrintln("Jоllу good, just the thing.");
Такого рода многоречивость необходима почти при каждом вызове метода, который вместо массива нулевой длины возвращает null. Это чревато ошибками, так как разработчик клиента мог и не написать специальный код для обработки результата null. Ошибка может оставаться незамеченной годами, поскольку подобные методы, как правило, возвращают один или несколько объектов. Следует еще упомянуть о том, что возврат null вместо массива приводит к усложнению самого метода, возвращающего массив. Иногда можно услышать возражения, что возврат значения null предпочтительнее возврата массива нулевой длины потому, что это позволяет избежать расходов на размещение массива в памяти. Этот аргумент несостоятелен по двум причинам. Во-первых, на этом уровне нет смысла беспокоиться о производительности, если только профилирование программы не покажет, что именно этот метод является основной причиной падения производительности. Во-вторых, при каждом вызове метода, который не возвращает записей, клиенту можно передавать один и тот же массив нулевой длины, поскольку любой массив нулевой длины неизменен, а неизменяемые объекты доступны для совместного использования. На самом деле, именно это и происходит, когда вы применяете стандартную идиому для выгрузки элементов из коллекции в массив с контролем типа:

private List сhееsеsInStосk = … ,
private fiпаl static Cheese[] NULL_CHEESE_ARRAY = nеw Cheese[0];
 /**
* @геtuгп массие, содержащий все сыры, имеющиеся в магазине
*/
public Cheese[] getCheeses() {
геtuгп (Cheese[] сhееsеsInStосk.tоАггау(NULL_СНЕЕSЕ_АRRАУ);  
}
В этой идиоме константа в виде массива нулевой длины передается методу toArray для того, чтобы показать, какой тип он должен возвратить. Обычно метод toArray выделяет место в памяти для возвращаемого массива, однако если коллекция пуста, она размещается во входном массиве, а спецификация Сollесtion,tоАггау(Оbjесt[]) дает гарантию, что если входной’ массив будет достаточно вместителен, чтобы содержать коллекцию, возвращен будет именно он. Поэтому представленная идиома никогда не будет сама размещать в памяти массив нулевой длины, а в качестве такового использует "константу с указанием типа". Подведем итоги. Нет никаких причин для того, чтобы работающий с массивами метод возвращал значение null, а не массив нулевой длины. Такая идиома, по-видимому, проистекает из языка программирования С, где длина массива возвращается отдельно от самого массива. В языке С бесполезно выделять память под массив нулевой длины. Источник: Джошуа Блох, Java TM Эффективное программирование, Издательство «Лори»
Комментарии (28)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
staxe Уровень 7
18 февраля 2023
Надеюсь в будущем вспомню и скажу "так вон оно чо"😬
Denis Odesskiy Уровень 33
11 декабря 2022
Жуть, стало очень страшно😵. До этой статьи всё было понятно...наверное я пока рано перешел по этой ссылке.
Egor Shalnev Уровень 3
30 ноября 2022
Мда, только запутали, спасибо комментариям ниже. Ощущение что статью переводили в гугл транслейт.
DEF Уровень 19
2 октября 2022
Пришел к этому принципу самостоятельно. Банально - так удобнее обрабатывать данные, тип однозначен, ошибки не падают, код проще. Никогда не любил функции с множественными типами возврата - всегда приходится проверять все типы. Но это нужно закреплять на уровне команды, потому что без контракта кто-то возвращает нулевые массивы, а кто-то null, false или exeption. Причем оговаривать нужно каждый конкретный кейс, потому что пустые массивы имеют смысл в основном если функция работает с группами сущностей, в остальных случаях может быть более корректно использовать другие решения. Да, тема эта не для новичков - споры о null return возникают обычно на основе какого-то опыта, на основе боли, которую вызывает null в тех или иных кейсах. Причем однозначного варианта нет, почему эти споры и не кончаются, т.е. null все таки иногда имеет смысл, правильной и неправильной позиции нет, все зависит от ситуации.
7 июля 2021
в последнем примере очепятка: * @геtuгп массие, содержащий все сыры, имеющиеся в магазине
Alexander G. Уровень 22
13 мая 2021
А мне зашла статья. Не знаю почему вы ругаете. Добавить в закладки и вспоминать об этом, когда на глаза попадётся, а через 10 раз запомню основательно :) Автору спасибо!
Игорь Уровень 22
10 марта 2021
Возврат массива нулевой это одно из возможных решений. Изначально проблемой является именно возврат null по описанным выше причинам. И избавиться от нее можно разными способами - выбросом checked исключения, возвращением массива нулевой длины. Правильность решения зависит от конкретной задачи.
Владимир Уровень 22
5 октября 2020
Мозг закипел!!!)
Olga Holovko Уровень 9
26 сентября 2020
Если вам нужно вернуть заполненный массив, как в первой задаче на массивы: return array;
🦔 Виктор Уровень 20 Expert
26 сентября 2020
Короче, вместо return null; делайте return new int[0]; И сильно голову этим на забивайте не первых порах, двигайтесь дальше. Статья сырая и больше путает, чем что-то объясняет. Удивительно, как можно было взять такую простую вещь и исковеркать её до нечитабельности. Ещё и ссылка на эту статью слишком рано попадается маленьким уровням.