User alexnjc
alexnjc
31 уровень

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

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

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 Эффективное программирование, Издательство «Лори»
Комментарии (21)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
Шалина Татьяна Уровень 15 Россия
7 июля 2021
в последнем примере очепятка: * @геtuгп массие, содержащий все сыры, имеющиеся в магазине
Alexander G. Уровень 15 Москва
13 мая 2021
А мне зашла статья. Не знаю почему вы ругаете. Добавить в закладки и вспоминать об этом, когда на глаза попадётся, а через 10 раз запомню основательно :) Автору спасибо!
Игорь Уровень 22 Москва Россия
10 марта 2021
Возврат массива нулевой это одно из возможных решений. Изначально проблемой является именно возврат null по описанным выше причинам. И избавиться от нее можно разными способами - выбросом checked исключения, возвращением массива нулевой длины. Правильность решения зависит от конкретной задачи.
null Уровень 0
14 февраля 2021
все предельно ясно, СМЬІСЛ -> ССЬІЛАТЬСЯ НА ТО, ЧТО ЕСТЬ В НАЛИЧИИ, так как ТО ЧЕГО НЕТ ВОПРОС НЕ РЕШАЕТ - ЗНАЧИТ ЛИШНЕ, МУСОР.
Владимир Уровень 20 Украина
5 октября 2020
Мозг закипел!!!)
Olga Holovko Уровень 9 Полтава Украина
26 сентября 2020
Если вам нужно вернуть заполненный массив, как в первой задаче на массивы: return array;
🦔 Виктор Уровень 20 Москва Россия Expert
26 сентября 2020
Короче, вместо return null; делайте return new int[0]; И сильно голову этим на забивайте не первых порах, двигайтесь дальше. Статья сырая и больше путает, чем что-то объясняет. Удивительно, как можно было взять такую простую вещь и исковеркать её до нечитабельности. Ещё и ссылка на эту статью слишком рано попадается маленьким уровням.
Александр Уровень 22 Москва
31 августа 2020
Как я понял, автор говорит, что лучше вернуть из метода ссылку на пустой массив (массив нулевой длины), чем ссылку на null (ссылка в никуда) То есть вместо кода: public Cheese[] getCheeses() { if (cheesesInStock.size() == 0) return null; } Создавать такой: public Cheese[] getCheeses() { if (cheesesInStock.size() == 0) return emptyArray; } где emptyArray объявлен и инициализирован так: Cheese[] emptyArray = new Cheese[0]
Серега Уровень 19 Кривой Рог Украина
22 августа 2020
https://www.youtube.com/playlist?list=PLyApprAtr5yjywFgRkxhfGfesgYoIhU8U
Alexandr Mihailovich Уровень 20 Kursk
28 апреля 2020
если хотели, чтобы понятные вещи стали более запутанными, то удалось. Масса опечаток говорит, что редакторы положили на все это дело нужно больше сыра объяснений