文章目录
在Optional出现之前经常遇到的空指针异常
我们的方法不应该返回null,
比如返回值为list时,我们可以构造一个空的list返回而不是null
空指针异常
Person
public class Person {
private Car car;
public Car getCar() {
return this.car;
}
}
Car
public class Car {
private Insurance insurance;
public Insurance getInsurance() {
return insurance;
}
}
Insurance
public class Insurance {
private String name;
public String getName() {
return name;
}
}
获取一个给车所上的报显
public static void main(String[] args) {
String insuranceName = getInsuranceName(new Person());
System.out.println(insuranceName);
}
private static String getInsuranceName(Person person) {
return person.getCar().getInsurance().getName();
}
这个显而易见会出现空指针异常
解决1 嵌套判断
public static void main(String[] args) {
String insuranceName = getInsuranceNameByDeepDoubts(new Person());
System.out.println(insuranceName); //UNKNOWN
}
private static String getInsuranceNameByDeepDoubts(Person person)
{
if (null != person) {
Car car = person.getCar();
if (null != car) {
Insurance insurance = car.getInsurance();
if (null != insurance) {
return insurance.getName();
}
}
}
return "UNKNOWN";
}
如果嵌套比较深,可读性会很差
解决2 多返回判断
看起来比较清晰
public static void main(String[] args) {
String insuranceName = getInsuranceNameByMultExit(new Person());
System.out.println(insuranceName); //UNKNOWN
}
private static String getInsuranceNameByMultExit(Person person)
{
final String defaultValue = "UNKNOWN";
if (null == person)
return defaultValue;
Car car = person.getCar();
if (null == car)
return defaultValue;
Insurance insurance = car.getInsurance();
if (null == insurance)
return defaultValue;
return insurance.getName();
}
optional
对我们的对象进行包装 避免空指针
创建
1 empty 及其 No value present 异常
Optional<Insurance> insuranceOptional = Optional.<Insurance>empty();
insuranceOptional.get();
所以这个构造方法会抛出异常
2 of
java.util.Objects#requireNonNull(T)
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
Optional<Insurance> insuranceOptional1 = Optional.of(new Insurance());
insuranceOptional1.get();
这个方法不会抛出异常
3 ofNullable
上面两种方法的综合 ofNullable
Optional<Insurance> objectOptional = Optional.ofNullable(null);
获取
1 orElseGet
objectOptional.orElseGet(Insurance::new);
如果有值返回值,没有则返回参数supplier中的值
2 orElse
objectOptional.orElse(new Insurance());
3 orElseThrow
objectOptional.orElseThrow(RuntimeException::new);
objectOptional.orElseThrow(() -> new RuntimeException("Not have reference"));
filter
Optional<Insurance> insurance1 = Optional.of(new Insurance());
Insurance insurance = insurance1.filter(i -> i.getName() == null).get();
System.out.println(insurance); //test.Insurance@723279cf
Insurance insurance = insuranceOptional1.filter(i -> i.getName() != null).get();
System.out.println(insurance);
map
Optional<Insurance> insurance1 = Optional.of(new Insurance());
Optional<String> nameOptional = insurance1.map(i -> i.getName());
System.out.println(nameOptional.orElse("empty Value"));
isPresent ifPresent
Optional<Insurance> insurance1 = Optional.of(new Insurance());
System.out.println(insurance1.isPresent());
insurance1.ifPresent(System.out::println);
回到1
改1 优化 flatmap
Person
public class Person {
private Optional<Car> car;
public Optional<Car> getCar() {
return this.car;
}
}
Car
public class Car {
private Optional<Insurance> insurance;
public Optional<Insurance> getInsurance() {
return insurance;
}
}
Insurance
public class Insurance {
private String name;
public String getName() {
return name;
}
}
OptionalInAction
public class OptionalInAction {
public static void main(String[] args) {
Optional.ofNullable(getInsuranceNameByOptional(new Person())).ifPresent(System.out::println);
}
private static String getInsuranceNameByOptional(Person person) {
return Optional.ofNullable(person)
.flatMap(Person::getCar).
flatMap(Car::getInsurance) .map(Insurance::getName).orElse("Unknown");
}
}
什么时候用map 什么时候用flatmap
java.util.Optional#flatMap
/**
* If a value is present, apply the provided {@code Optional}-bearing
* mapping function to it, return that result, otherwise return an empty
* {@code Optional}. This method is similar to {@link #map(Function)},
* but the provided mapper is one whose result is already an {@code Optional},
* and if invoked, {@code flatMap} does not wrap it with an additional
* {@code Optional}.
*
* @param <U> The type parameter to the {@code Optional} returned by
* @param mapper a mapping function to apply to the value, if present
* the mapping function
* @return the result of applying an {@code Optional}-bearing mapping
* function to the value of this {@code Optional}, if a value is present,
* otherwise an empty {@code Optional}
* @throws NullPointerException if the mapping function is null or returns
* a null result
*/
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));
}
}
java.util.Optional#map
/**
* If a value is present, apply the provided mapping function to it,
* and if the result is non-null, return an {@code Optional} describing the
* result. Otherwise return an empty {@code Optional}.
*
* @apiNote This method supports post-processing on optional values, without
* the need to explicitly check for a return status. For example, the
* following code traverses a stream of file names, selects one that has
* not yet been processed, and then opens that file, returning an
* {@code Optional<FileInputStream>}:
*
* <pre>{@code
* Optional<FileInputStream> fis =
* names.stream().filter(name -> !isProcessedYet(name))
* .findFirst()
* .map(name -> new FileInputStream(name));
* }</pre>
*
* Here, {@code findFirst} returns an {@code Optional<String>}, and then
* {@code map} returns an {@code Optional<FileInputStream>} for the desired
* file if one exists.
*
* @param <U> The type of the result of the mapping function
* @param mapper a mapping function to apply to the value, if present
* @return an {@code Optional} describing the result of applying a mapping
* function to the value of this {@code Optional}, if a value is present,
* otherwise an empty {@code Optional}
* @throws NullPointerException if the mapping function is null
*/
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));
}
}