Никто не любит исключения Null Pointer ! Есть ли способ, которым мы можем избавиться от них?
Может быть . , ,
Несколько методов были обсуждены в этом посте:
- Необязательный тип (новый в Java 8)
- Класс объектов (старый Java 7!)
Необязательный тип в Java 8
Что это такое?
- Новый тип (класс), представленный в Java 8
- Предназначен для использования в качестве « оболочки » для объекта определенного типа или для сценариев, в которых нет объекта (null)
Проще говоря, это лучшая замена для обработки нулей ( предупреждение : на первый взгляд это может быть не очень очевидно!)
Основное использование
Это тип (класс) — так, как мне создать его экземпляр?
Просто используйте три статических метода в классе Optional.
|
1
2
3
|
public static Optional<String> stringOptional(String input) { return Optional.of(input);} |
Просто и понятно — создайте опциональную оболочку, содержащую значение. Осторожно — бросит NPE, если само значение равно нулю!
|
1
2
3
4
5
6
7
|
public static Optional<String> stringNullableOptional(String input) { if (!new Random().nextBoolean()) { input = null; } return Optional.ofNullable(input);} |
Чуть лучше по моему личному мнению. Здесь нет риска NPE — в случае нулевого ввода будет возвращен пустой Optional.
|
1
2
3
|
public static Optional<String> emptyOptional() { return Optional.empty();} |
Если вы хотите целенаправленно вернуть «пустое» значение. «пустой» не означает ноль .
Хорошо — как насчет потребления / использования дополнительного?
|
1
2
3
4
5
6
7
8
9
|
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) . Не волнуйтесь, я тоже это объясню.
|
1
2
3
4
5
6
7
8
|
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 перед извлечением фактического значения.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
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 — как упоминалось в приведенных выше примерах, использование Optional.ofNullable (во время создания Optional) и orElse и orElseGet (во время использования Optional) полностью защищает нас от NPE.
Еще один спаситель!
(если вы не можете использовать Java 8)
Посмотрите на этот фрагмент кода.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
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, мы никогда не можем быть уверены, что равно нулю ?
Войдите в класс объектов
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
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 . Это, наряду с вашим собственным сообщением об ошибке , поможет вам быстрее обнаруживать ошибки. , .Гораздо быстрее ИМО!
Вы также можете написать свои определенные пользователем проверки, например, реализовать простую проверку, которая обеспечивает не пустоту
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
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; } }} |
Не позволяйте NPE быть болью в неправильном месте. В нашем распоряжении имеется более чем приличный набор инструментов для лучшей работы с NPE или их полного искоренения!
Ура!
| Ссылка: | Необязательно и объекты: Null Pointer Saviors! от нашего партнера JCG Абхишека Гупты в блоге Object Oriented .. |