public class A {
private B b;
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
}
public class B {
private String bName;
private String bAge;
public String getbName() {
return bName;
}
public void setbName(String bName) {
this.bName = bName;
}
public String getbAge() {
return bAge;
}
public void setbAge(String bAge) {
this.bAge = bAge;
}
}
复制代码
已经存在两个类,而且互相嵌套,并且不容许修改, A 、B 两个类的结构,咱们要安全的访问 A B中的值,尽量少的使用 if
语句。java
A a = null;
Optional<A> a1 = Optional.ofNullable(a);
Optional<B> b = a1.filter((t) -> t.getB() != null).map(A::getB);
// 上面一行代码的问题是, t 有可能会为 null ,从而引起 NPE
B b2 = b.get();
复制代码
Optional<A> a1 = Optional.ofNullable(a);
Optional<B> b = a1.map(A::getB);
b.get(); // 有可能会抛异常,由于若是 b 为 null,那么获得的 Optional 为 empty 建立的
b.orElse(new B()); // 没有问题,返回 new B 的对象
b.orElseGet(() -> B :: new); // 没有问题,返回 new B 的对象
b.orElseThrow(() -> YdException::new); // 手动抛出异常
复制代码
public class PersonNoOptional {
private Car car;
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public static class Car{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
复制代码
上面的代码是没有使用 Optional 时候,咱们常常会写的样式。会出现的问题:设计模式
咱们的解决方式安全
public class OptionService {
public void opt() {
PersonNoOptional p = new PersonNoOptional();
PersonNoOptional.Car car = p.getCar();
if (car != null) {
// ....
}
}
}
复制代码
会添加不少的 if
来进行判断,甚至还有空对象设计模式(Null Object Pattern) 来处理这一类的问题。Java 8 为咱们带来了 Optional
添加新的解决方式。函数
public class PersonOptional {
private Optional<PersonNoOptional.Car> car;
public Optional<PersonNoOptional.Car> getCar() {
return car;
}
public void setCar(PersonNoOptional.Car car) {
this.car = Optional.of(car);
}
public static class Car {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
复制代码
Peron 有可能会没有 Car,可是每一辆 Car 都必须有 name,因此咱们对 Car 使用了 Optional 包装,而 name 没有使用 Optional 的缘由就在这里。ui
建立一个空的 Optional
对象this
Optional<Object> empty = Optional.empty();
复制代码
private static final Optional<?> EMPTY = new Optional<>();
private Optional() { this.value = null; }
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
复制代码
Optional<B> optionalB = Optional.of(new B());
复制代码
of 方法中的参数若是为 null,会发生 NPEspa
Optional<Object> optional = Optional.of(null);
复制代码
// Objects.requireNonNull 的实现
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
复制代码
ofNullable 容许传入的参数为 null设计
A a = null;
Optional<A> optonal = Optional.ofNullable(a);
复制代码
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
复制代码
#Optinal 中获取值code
A a = optionalA.get();
复制代码
若是 Optional
容器中不存在值,会抛出异常 NoSuchElementException("No value present")
对象
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
复制代码
A a = optionalA.orElse(new A());
复制代码
若是 Optional
容器中不存在值,使用 orElse
方法中定义的值。
public T orElse(T other) {
return value != null ? value : other;
}
复制代码
A a = optionalA.orElseGet(A::new);
复制代码
若是 Optional
容器中不存在值,会执行定义的函数。
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
复制代码
A a = optionalA.orElseThrow(RuntimeException::new);
复制代码
若是 Optional
容器中不存在值,会抛出指定的异常。与 get
方法的区别是,get
方法抛出的异常为固定的,该方法能够抛出指定的异常。
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
复制代码
当 Optional
容器中的值为空时,使用了 throw
关键字。
public class A {
private B b;
public B getB() {
return b;
}
}
public class B {
private Name bName;
private String bAge;
public Name getbName() {
return bName;
}
public void setbName(Name bName) {
this.bName = bName;
}
public String getbAge() {
return bAge;
}
public void setbAge(String bAge) {
this.bAge = bAge;
}
public static class Name{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
复制代码
A B 两个类的结构关系是互相嵌套,咱们要取出 b.Name.getName() 的值
Optional<String> aName = optionalA.map(A::getB)
.map(B::getbName)
.map(B.Name::getName);
System.out.println(aName.orElse("kkk"));
复制代码
若是 B 在 A 的嵌套中,使用了 Optional 包装
public class A {
private Optional<B> b;
public Optional<B> getB() {
return b;
}
}
复制代码
再使用上面的访问,就会编译报错。
缘由:
Optional<Optional<B>> optional = optionalA.map(A::getB);
复制代码
map 的返回外面被包装了一层 Optional
,想要达到上面的效果,须要拆掉一层 Optional
的包装,那么此时就可使用 flatMap
来打散一层 Optional
的包装
String kkk = optionalA.flatMap(A::getB)
.map(B::getbName)
.map(B.Name::getName)
.orElse("kkk");
复制代码
ypxh就能够顺利访问了
map 和 flatMap 的区别在于,flatMap 会进行拆包(将外面的层包装拆除)的动做,而 map 不会进行拆包
isPresent 用于判断 Optional
容器中值是否为空(null),不为空返回会 true,空返回 false
public boolean isPresent() {
return value != null;
}
复制代码
ifPresent 提供了执行函数式代码的能力,当 Optional
容器中的值不为空时,会执行传入的函数式代码。
optionalA.ifPresent(c -> System.out.println(c.getB()));
复制代码
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
复制代码
经过执行传入的谓词
进行过滤,若是传入的 谓词
执行结果为 true
返回 Optional
容器自己,不然返回空容器。
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
复制代码