Никто не любит исключения Null Pointer ! Есть ли способ, которым мы можем избавиться от них? Может быть . , ,
Несколько методов были обсуждены в этом посте
- Необязательный тип (новый в Java 8)
- Класс объектов (старый Java 7 материал ;-))
Необязательный тип в Java 8
Что это?
- Новый тип (класс), представленный в Java 8
- Предназначен для использования в качестве « оболочки » для объекта определенного типа или для сценариев, в которых нет объекта (null)
Проще говоря, это лучшая замена для обработки нулей ( предупреждение : на первый взгляд это может быть не очень очевидно!)
Основное использование
Это тип (класс) — так, как мне создать его экземпляр?
Просто используйте три статических метода в классе Optional
public static Optional<String> stringOptional(String input) {
return Optional.of(input);
}
Просто и понятно — создайте опциональную оболочку, содержащую значение. Осторожно — бросит NPE, если само значение равно нулю!
public static Optional<String> stringNullableOptional(String input) {
if (!new Random().nextBoolean()) {
input = null;
}
return Optional.ofNullable(input);
}
будет возвращен пустой
Optional
public static Optional<String> emptyOptional() {
return Optional.empty();
}
«пустой» не означает ноль
Хорошо — как насчет потребления / использования дополнительного?
public static void consumingOptional() {
Optional<String> wrapped = Optional.of("aString");
if (wrapped.isPresent()) {
System.out.println("Got string - " + wrapped.get());
}
else {
System.out.println("Gotcha !");
}
}
метод isPresent
) — это заставит вас задуматься, а не лучше
ли
использовать if (myObj! = Null) ? Не волнуйтесь, я объясню как хорошо
public static void consumingNullableOptional() {
String input = null;
if (new Random().nextBoolean()) {
input = "iCanBeNull";
}
Optional<String> wrapped = Optional.ofNullable(input);
System.out.println(wrapped.orElse("default"));
}
orElse,
который можно использовать для возврата
значения по умолчанию
в случае, если обернутое значение равно нулю — преимущество очевидно. Мы
избегаем
очевидного многословия вызова
ifPresent
перед извлечением фактического значения
public static void consumingEmptyOptional() {
String input = null;
if (new Random().nextBoolean()) {
input = "iCanBeNull";
}
Optional<String> wrapped = Optional.ofNullable(input);
System.out.println(wrapped.orElseGet(
() -> {
return "defaultBySupplier";
}
));
}
orElse
и
orElseGet
вполне могли быть
перегружены
(то же имя, другой параметр)
В любом случае, единственным очевидным отличием здесь является сам параметр — у вас есть возможность предоставить лямбда-выражение, представляющее экземпляр поставщика <T> (функциональный интерфейс)
Как использование Optional лучше, чем обычные проверки нуля ????
- В общем и целом, главное преимущество использования Optional заключается в том, чтобы иметь возможность четко выразить свое намерение — простой возврат нулевого значения из метода оставляет потребителя в море сомнений (когда происходит фактический NPE) относительно того, было ли оно преднамеренным или нет. и требует дальнейшего самоанализа в Javadocs (если таковые имеются). С Факультативным, его кристально чистый !
- Есть способы , в которых вы можете полностью избежать NPE с Опционно — как указаны в приведенном выше примерах, использование Optional.ofNullable (при Факультативным создании) и OrElse и orElseGet (при Факультативным потреблении) оградить нас от неработающих вообще
Еще один спаситель! ( если вы не можете использовать Java 8 )
Посмотрите на этот фрагмент кода
package com.abhirockzz.wordpress.npesaviors;
import java.util.Map;
import java.util.Objects;
public class UsingObjects {
String getVal(Map<String, String> aMap, String key) {
return aMap.containsKey(key) ? aMap.get(key) : null;
}
public static void main(String[] args) {
UsingObjects obj = new UsingObjects();
obj.getVal(null, "dummy");
}
}
- Объект карты
- Ключ, по которому выполняется поиск
- Экземпляр, в котором вызывается метод
Когда в этом случае выбрасывается NPE, мы никогда не можем быть уверены, что равно нулю ?
Войдите в класс объектов
package com.abhirockzz.wordpress.npesaviors;
import java.util.Map;
import java.util.Objects;
public class UsingObjects {
String getValSafe(Map<String, String> aMap, String key) {
Map<String, String> safeMap = Objects.requireNonNull(aMap,
"Map is null");
String safeKey = Objects.requireNonNull(key, "Key is null");
return safeMap.containsKey(safeKey) ? safeMap.get(safeKey) : null;
}
public static void main(String[] args) {
UsingObjects obj = new UsingObjects();
obj.getValSafe(null, "dummy");
}
}
RequireNonNull
метод
- Просто возвращает значение в случае, если оно не равно нулю
- Бросает NPE будет указанное сообщение в случае, если значение в ноль
Почему это лучше, чем если (myObj! = Null)
Трассировки стека , который вы увидите , будет ясно иметь Objects.requireNonNull вызов метода. Это, наряду с вашим собственным сообщением об ошибке , поможет вам быстрее обнаруживать ошибки. , намного быстрее ИМО!
Вы также можете написать свои определенные пользователем проверки, например, реализовать простую проверку, которая обеспечивает не пустоту
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
public class RandomGist {
public static <T> T requireNonEmpty(T object, Predicate<T> predicate, String msgToCaller){
Objects.requireNonNull(object);
Objects.requireNonNull(predicate);
if (predicate.test(object)){
throw new IllegalArgumentException(msgToCaller);
}
return object;
}
public static void main(String[] args) {
//Usage 1: an empty string (intentional)
String s = "";
System.out.println(requireNonEmpty(Objects.requireNonNull(s), (s1) -> s1.isEmpty() , "My String is Empty!"));
//Usage 2: an empty List (intentional)
List list = Collections.emptyList();
System.out.println(requireNonEmpty(Objects.requireNonNull(list), (l) -> l.isEmpty(), "List is Empty!").size());
//Usage 3: an empty User (intentional)
User user = new User("");
System.out.println(requireNonEmpty(Objects.requireNonNull(user), (u) -> u.getName().isEmpty(), "User is Empty!"));
}
private static class User {
private String name;
public User(String name){
this.name = name;
}
public String getName(){
return name;
}
}
}
Ура! ?