Возможности функционального программирования, привнесенные Java8, по-прежнему имеют определенные препятствия для программистов, привыкших к императивному программированию, и только глубоко понимая все аспекты этих механизмов, мы можем использовать их свободно. Обработка нулей — еще одна головная боль в JAVA-программировании, помимо try catch, требует много непустого кода шаблона суждения, а логика программы слишком глубоко вложена. Специально для использования сетов необходимо судить о пустом слой за слоем.
Сначала взгляните на структурную схему класса Optional:
Атрибуты
/**
* Common instance for {@code empty()}.
*/
private static final Optional<?> EMPTY = new Optional<>();
/**
* If non-null, the value; if null, indicates no value is present
*/
private final T value;
1) EMPTY содержит пустую структуру значений определенного типа, и экземпляр, возвращаемый вызовом empty(), является экземпляром
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
2) T vaule – это значение, удерживаемое структурой
метод
Конструктор
private Optional() {
this.value = null;
}
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
Необязательный (значение T) вызовет исключение NullPointer, если значение имеет значение null, поэтому оба конструктора подходят для использования в сценариях.
Создать необязательный объект
Существует два метода (T) и ofNullable(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);
}
of — это конструктор, который вызывается напрямую, поэтому, если T имеет значение null, будет выдано исключение нулевого указателя, а ofNullable обрабатывает null и возвращает экземпляр EMPTY, поэтому исключения не возникнет.
Таким образом, вы можете использовать напрямую только для объектов, которые определенно не являются нулевыми.
Получить значение необязательного объекта
Использование, от которого нужно отказаться
if(value.isPresent){
….
}else{
T t = value.get();
}
Это использование эквивалентно традиционному if(vaule != null)
Правильная поза использования:
orElse: возвращает указанное значение, если значение пусто.
orElseGet: если значение пусто, вызовите указанный метод и верните
orElseThrow: генерирует исключение, если значение пусто
public T orElse(T other) {
return value != null ? value : other;
}
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
Как правило, мы используем orElse для получения значения, если оно не существует, возвращаем значение по умолчанию.
Промежуточная обработка Факультативного
filter, map, flatMap, эти операции аналогичны потоковой обработке, но следует отметить, что при обработке flatMap необходимо вручную указать тип возвращаемого значения как необязательный, а карта автоматически перенесет возвращаемое значение как необязательный. Например, у нас есть продукты, которые имеют очень упорядоченную структуру:
package model;
import java.util.List;
/**
* @auth gongxufan
* @Date 2016/10/23
**/
public class Goods {
private String goodsName;
private double price;
private List<Order> orderList;
public String getGoodsName() {
return goodsName;
}
public void setGoodsName(String goodsName) {
this.goodsName = goodsName;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public List<Order> getOrderList() {
return orderList;
}
public void setOrderList(List<Order> orderList) {
this.orderList = orderList;
}
}
package model;
import java.time.LocalDateTime;
/**
* @auth gongxufan
* @Date 2016/10/23
**/
public class Order {
private LocalDateTime createTime;
private LocalDateTime finishTime;
private String orderName;
private String orderUser;
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getFinishTime() {
return finishTime;
}
public void setFinishTime(LocalDateTime finishTime) {
this.finishTime = finishTime;
}
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
public String getOrderUser() {
return orderUser;
}
public void setOrderUser(String orderUser) {
this.orderUser = orderUser;
}
}
Теперь у меня есть товар по желанию
Optional<Goods> goodsOptional = Optional.ofNullable(new Goods());
Теперь мне нужно получить список заказов в товарах. Необязательно, вы должны сделать это
goodsOptional.flatMap(g ->Optional.ofNullable(g.getOrderList())).orElse(Collections.emptyList())
То, что возвращается в flatMap, является необязательным>, а затем мы используем orElse для развертки, поэтому faltMap может разыменовывать более глубокие цепочки объектов.
Обнаружить необязательно и выполнить действие
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
Это терминальная операция, в отличие от вышеописанной, которую можно связать в цепочку. Используйте прямой вызов в опциональном экземпляре, если значение существует, будет вызван указанный метод потребления. Например:
Goods goods = new Goods();
Optional<Goods> goodsOptional = Optional.ofNullable(goods);
List<Order> orderList = new ArrayList<>();
goods.setOrderList(orderList);
goodsOptional.flatMap(g ->Optional.ofNullable(g.getOrderList())).ifPresent((v)-> System.out.println(v));
end
На данный момент методы и использование этого класса почти одинаковы.Наконец, мы суммируем моменты, на которые необходимо обратить внимание:
1) Необязательный нужно использовать только для обработки возвращаемого значения, а не как поле класса или параметр метода, потому что это вызовет дополнительную сложность.
2) При использовании Option вам следует избегать использования конструктора и получения напрямую, и вы должны использовать серию методов orElse, чтобы избежать частых ненулевых суждений.
3) карта и плоская карта должны обращать внимание, чтобы различать сценарии использования