Это очень распространенная проблема для каждого Java-разработчика. Так что в Java 8 есть официальная поддержка для решения этих проблем без загроможденного кода.
Java 8 представила java.util.Optional<T>
. Это контейнер, который может содержать или не содержать ненулевое значение. Java 8 предоставила более безопасный способ обработки объекта, значение которого может быть нулевым в некоторых случаях. Он вдохновлен идеями Haskell и Scala .
В двух словах, в классе Optional есть методы для явного обращения со случаями, когда значение присутствует или отсутствует. Однако преимущество по сравнению с нулевыми ссылками заключается в том, что дополнительный класс заставляет задуматься о случае, когда значение отсутствует. Как следствие, вы можете предотвратить непреднамеренные исключения нулевого указателя.
В приведенном выше примере у нас есть фабрика обслуживания на дому, которая возвращает ручку нескольким бытовым приборам. Но эти услуги могут быть или не быть доступными / функциональными; это означает, что это может привести к NullPointerException. Вместо добавления нулевого условия if
перед использованием какого-либо сервиса, давайте обернем его в Необязательный .
ОБОРОТ ДЛЯ ВАРИАНТА
Давайте рассмотрим метод получения ссылки на сервис с фабрики. Вместо того, чтобы возвращать сервисную ссылку, оберните ее необязательно. Это позволяет пользователю API знать, что возвращенный сервис может или не может быть доступен / функционален, использовать для защиты
public Optional<Service> getRefrigertorControl() {
Service s = new RefrigeratorService();
//...
return Optional.ofNullable(s);
}
Как видите, Optional.ofNullable()
предоставляет простой способ обернуть ссылку. Есть и другие способы получить ссылку на Optional, либо Optional.empty()
& Optional.of()
. Один для возврата пустого объекта вместо перенастройки null, а другой для переноса ненулевого объекта соответственно.
ТАК КАК ТОЛЬКО ЭТО ПОМОГАЕТ ИЗБЕЖАТЬ ПУСТОЙ ПРОВЕРКИ?
После того, как вы обернули ссылочный объект, в Optional есть много полезных методов для вызова методов в обернутой ссылке без NPE.
Optional ref = homeServices.getRefrigertorControl();
ref.ifPresent(HomeServices::switchItOn);
Optional.ifPresent вызывает данного Потребителя со ссылкой, если это ненулевое значение. В противном случае это ничего не делает.
@FunctionalInterface
public interface Consumer<T>
Представляет операцию, которая принимает один входной аргумент и не возвращает результата. В отличие от большинства других функциональных интерфейсов, ожидается, что потребитель будет работать через побочные эффекты.
Это так чисто и легко понять. В приведенном выше примере кода HomeService.switchOn(Service)
вызывается, если необязательная ссылка удержания не равна нулю.
Мы очень часто используем троичный оператор для проверки нулевого условия и возвращаем альтернативное значение или значение по умолчанию. Необязательно предоставляет другой способ обработки того же условия без проверки нулевого значения. Optional.orElse (defaultObj) возвращает defaultObj, если Optional имеет нулевое значение. Давайте использовать это в нашем примере кода:
public static Optional<HomeServices> get() {
service = Optional.of(service.orElse(new HomeServices()));
return service;
}
Теперь HomeServices.get () делает то же самое, но лучше. Проверяет, инициализирован ли сервис или нет. Если это так, верните то же самое или создайте новый новый сервис. Необязательный .orElse (T) помогает вернуть значение по умолчанию.
Наконец, вот наш NPE, а также нулевой код без проверки:
import java.util.Optional;
public class HomeServices {
private static final int NOW = 0;
private static Optional<HomeServices> service;
public static Optional<HomeServices> get() {
service = Optional.of(service.orElse(new HomeServices()));
return service;
}
public Optional<Service> getRefrigertorControl() {
Service s = new RefrigeratorService();
//...
return Optional.ofNullable(s);
}
public static void main(String[] args) {
/* Get Home Services handle */
Optional<HomeServices> homeServices = HomeServices.get();
if(homeServices != null) {
Optional<Service> refrigertorControl = homeServices.get().getRefrigertorControl();
refrigertorControl.ifPresent(HomeServices::switchItOn);
}
}
public static void switchItOn(Service s){
//...
}
}
Полный текст сообщения: NPE, а также пустой код без проверки ... Действительно? .