Много раз, когда я выбираю значение из некоторой иерархии данных, я проверяю себя на нуль, чтобы избежать исключений NullPointerExceptions, которые, как я считаю, подвержены ошибкам и требуют большого количества шаблонов.
Я написал очень простую процедуру, которая позволяет мне пропустить проверку нуля при получении объекта ...
public final class NoNPE {
public static <T> T get(NoNPEInterface<T> in) {
try {
return in.get();
} catch (NullPointerException e) {
return null;
}
}
public interface NoNPEInterface<T> {
T get();
}
}
Я использую это немного как это ...
Room room = NoNPE.get(() -> country.getTown().getHouses().get(0).getLivingRoom());
Вышеприведенный результат привел к тому, что я получил объект Room или ноль, не проверяя все родительские уровни на ноль.
Что вы думаете о вышесказанном? Я создаю проблемный образец? Есть ли лучший способ сделать это по вашему мнению?
java.util.Optional
вместо нулей для представления отсутствующих данных? Это предоставляет удобные утилиты как для описываемого вами случая, так и для случаев, когда вы хотите продолжить работу с данными по умолчанию, а не просто возвращать условие сбоя в конце цепочки ..Option
(илиMaybe
) монаду :)Ответы:
Ваше решение очень умное. Проблема, которую я вижу, в том, что вы не знаете, почему у вас есть
null
? Это потому, что в доме не было комнат? Было ли это потому, что в городе не было домов? Это потому, что в стране не было городов? Было ли это из-null
за ошибки в позиции 0 из-за ошибки, даже если дома находятся в позициях 1 и выше?Если вы используете расширенный
NonPE
класс, у вас будут серьезные проблемы с отладкой. Я думаю, что лучше знать, где именно разрывается цепь, чем молча получить сообщение,null
которое может скрывать более глубокую ошибку.Кроме того, это нарушает закон Деметры :
country.getTown().getHouses().get(0).getLivingRoom()
. Чаще всего нарушение какого-то хорошего принципа заставляет вас искать неортодоксальные решения для решения проблемы, вызванной нарушением такого принципа.Я рекомендую вам использовать его с осторожностью и попытаться устранить конструктивный недостаток, из-за которого вам придется столкнуться с антипаттерном крушения поезда (поэтому вам не придется использовать его
NonPE
повсюду). В противном случае у вас могут быть ошибки, которые будет трудно обнаружить.источник
Option
монаду, вам все равно, где в цепочке отсутствует значение. Когда вы заботитесь об этом, вы, вероятно, используете другой тип, напримерEither
.?.
и?[]
операторам. Одним из примеров того, когда вы можете захотеть использовать такую вещь, являются иерархические настройки на стороне сервера.var shouldDoThing = settings?.a?.b?.c ?? defaultSetting;
Кого волнует, почему какая-то часть этого была нулевой? Может быть, вы не смогли получить настройки. Может быть, вы решили удалить раздел настроек. В любом случае, вы никогда не сможете рассчитывать на получение настроек сервера, поэтому по умолчанию это хорошая идея, и вам вряд ли интересно, почему вы не можете получить фактические настройки, если это не происходит очень часто, когда этого не следует делать. ,settings.a.b.c
. Опять же, это единственный изолированный пример.Идея хорошая, действительно хорошая на самом деле. Поскольку в Java 8
Optional
существуют типы, подробное объяснение можно найти в дополнительном типе Java . Пример с тем, что вы опубликовалиИ дальше.
источник
Optional
является более читабельным решением из двух, хотя бы потому, что - в отличие от вашего предложения - это очень распространенная идиома. Это даже более кратко, чем у вас!Ваш метод работает достаточно хорошо для его предназначения, хотя возвращает
null
s, когда вы получаетеNullPointerException
звуки, похожие на плохой дизайн.Старайтесь избегать
null
s, когда вы можете, и передавать их только тогда, когда они представляют что-то или имеют особое значение, и возвращать их только тогда, когда они представляют / значат что-то, иначе вы должны бросить aNullPointerException
. Это позволяет избежать ошибок и путаницы. Если неObject
должно бытьnull
,NullPointer
должно быть брошено. Если объект может быть,null
тогда ничто не пойдет не так, когда его передадут. В противном случае ваш метод работает выше.источник
Я чувствую вашу боль, но предложенное решение - плохая идея.
NoNPE.get
.Optional.map
это то , что вы ищете.Как примечание стороны,
NoNPEInterface
является дубликатомjava.util.function.Supplier
.В некоторых случаях вы можете рассмотреть возможность использования утилит для оценки выражений, которые присутствуют во многих средах (например, EL, SpEL):
источник