Optional principal problem is the infamous null pointer exception (NullPointerException). There is an optional value that contains wrapper classes, which means Optional classes can contain both objects can also be empty.
May produce abnormalities in this code space;
String isocode = user.getAddress().getCountry().getIsocode().toUpperCase(); //需要检查: if (user != null) { Address address = user.getAddress(); if (address != null) { Country country = address.getCountry(); if (country != null) { String isocode = country.getIsocode(); if (isocode != null) { isocode = isocode.toUpperCase(); } } } }
Optional classes are still dependent on the function interface that set of things:
import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier;
Oriented programming interface is to make a go in the end. Only one private field:
private final T value;
Native code is quite simple:
public static<T> Optional<T> empty() { @SuppressWarnings("unchecked") Optional<T> t = (Optional<T>) EMPTY; return t; } public static <T> Optional<T> of(T value) { return new Optional<>(value); } public static <T> Optional<T> ofNullable(T value) { return value == null ? empty() : of(value); } public<U> Optional<U> map(Function<? super T, ? extends U> mapper) { Objects.requireNonNull(mapper); if (!isPresent()) return empty(); else { return Optional.ofNullable(mapper.apply(value)); } } ......
Creating Optional package instance
Built empty
Optional<Insurance> emptyOpt = Optional.empty(); try { Insurance obj = emptyOpt.get(); System.out.println("不为空"); } catch (NoSuchElementException ex) { System.out.println("为空"); }
EmptyOpt try to access the variable values cause NoSuchElementException, because the soundtrack Code:
public T get() { if (value == null) { throw new NoSuchElementException("No value present"); } return value; }
Construction may be empty (ofNullable not throw an exception)
Optional<Insurance> opt = Optional.ofNullable(null);
Not abnormally
so amazing, because the native code has been sentenced to empty, given the private value became empty (), which does not throw an exception also have a problem that in instances when the consumer, or to filter out empty value.
public static <T> Optional<T> ofNullable(T value) { return value == null ? empty() : of(value); }
Throw an exception when construction is empty (that is, of non-empty)
public static void whenCreateOfEmptyOptional_thenNullPointerException() { Insurance ins = new Insurance(); Optional<Insurance> opt = Optional.of(ins); ins=null; try { opt = Optional.of(ins); System.out.println("不为空"); } catch (NullPointerException ex) { System.out.println("为空"); } }
It will enter exception. Tracking native code found out the reason:
public static <T> T requireNonNull(T obj) { if (obj == null) throw new NullPointerException(); return obj; }
Value Optional object access
get
One way to retrieve the actual value of the object instance is to use the Optional get () method:
@Test public void whenCreateOfNullableOptional_thenOk() { String name = "John"; Optional<String> opt = Optional.ofNullable(name); assertEquals("John", opt.get()); }
This method throws an exception if the value is null. To avoid exceptions, you can choose to first verify whether there are values:
@Test public void whenCheckIfPresent_thenOk() { User user = new User("[email protected]", "1234"); Optional<User> opt = Optional.ofNullable(user); assertTrue(opt.isPresent()); assertEquals(user.getEmail(), opt.get().getEmail()); }
The use ifPresent
Native code:
public void ifPresent(Consumer<? super T> consumer) { if (value != null) consumer.accept(value); }
Only when the value is not empty, before the implementation of method consumers accept, it is relatively safe.
public static void printName(Insurance obj) { Optional.ofNullable(obj).ifPresent(u -> System.out.println("The name is : " + u.getName())); } Insurance obj = new Insurance(); obj.setName("张三"); Insurance objNull = null; printName(obj); printName(objNull); //输出:The name is : 张三
The use isPresent
With feeling ifPresent, then you do not need to judge isPresent empty, otherwise I feel very long-winded.
orElse use
Return to the default value when the object is empty. The way it works is straightforward, if the value of the value is returned, otherwise the value parameter passed to it.
Insurance obj = new Insurance(); obj.setName("张三"); Insurance objNull = null; Insurance result = Optional.ofNullable(objNull).orElse(obj); System.out.println(obj.hashCode()); System.out.println(result.hashCode());
The actual result is returned obj, instead of null.
filter use
filter () method takes as parameters Predicate object, the object is used to filter Optional, if they meet the conditions of Predicate returns Optional object itself, otherwise an empty Optional objects
public static void filterAge(Student student) { Optional.ofNullable(student).filter( u -> u.getAge() > 18).ifPresent(u -> System.out.println("The student age is more than 18.")); }
Use the map
parameter map () method of Function (function interface) objects, map () method Optional the wrapper object calculates a Function functions, and packaged into new Optional objects (type wrapper object may vary)
native code:
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) { Objects.requireNonNull(mapper); if (!isPresent()) return empty(); else { return Optional.ofNullable(mapper.apply(value)); } }
The following code, the first () method is configured with ofNullable a Optional <Student> object, and then calculate the age of the students using map (), returns Optional <Integer> object (if the student is null, returns the map () method returns an empty Optinal Object)
public static Optional<Integer> getAge(Student student) { return Optional.ofNullable(student).map(u -> u.getAge()); }
flatMap use
With map () method is different, the reference function's return value Function type Optional <U> type, rather than U type, such flatMap () Optional objects capable of a two-dimensional map into a one-dimensional object,
sum , map into what is out of the same dimensions, flatMap to shoot flat results.
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) { Objects.requireNonNull(mapper); if (!isPresent()) return empty(); else { return Objects.requireNonNull(mapper.apply(value)); } } //例子 Optional<String> nonEmptyGender = Optional.of("male"); Optional<String> emptyGender = Optional.empty(); System.out.println("Non-Empty Optional:: " + nonEmptyGender.map(String::toUpperCase)); System.out.println("Empty Optional :: " + emptyGender.map(String::toUpperCase)); Optional<Optional<String>> nonEmptyOtionalGender = Optional.of(Optional.of("male")); System.out.println("Optional value :: " + nonEmptyOtionalGender); System.out.println("Optional.map :: " + nonEmptyOtionalGender.map(gender -> gender.map(String::toUpperCase))); System.out.println("Optional.flatMap :: " + nonEmptyOtionalGender.flatMap(gender -> gender.map(String::toUpperCase)));
The package may be null
Use ofNullable, such as in some key map is used it is empty:
Optional<Insurance> opt = Optional.ofNullable(map.get("someNullKey"));