java.util.optional是从JDK 8起头引的类,Optional是一个包含了空值(NULL)或非空值(NOT NULL)的对象容器,用于判断方式的返回类型是否有值,Optional的优点是能够避免因为NULL带来的非常情形,如NullPointerException。一样地,若是一个方式的返回类型是Optional,则该方式应该经量避免返回NULL,对应的应该返回一个包含了NULL对象的Optional实例。提醒:本文编写时使用的是JDK 8
Optional源码剖析
Optional是一个对象容器,你能够在java.util包中找到该类。接下来,将剖析Optional类中的组织器,属性和方式。Optional类的源码和剖析如下:public final class Optional<T> {
/**
* EMPTY代表NULL值的Optional对象实例
*/
private static final Optional<?> EMPTY = new Optional<>();
/**
* 泛型类型的对象实例
*/
private final T value;
/**
* 私有的Optional空组织函数
*/
private Optional() {
this.value = null;
}
/**
* 返回内部的EMPTY实例
*/
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
/**
* 经由value实例化Optional对象,若是value为空,则抛出空指针非常
*/
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
/**
* 经由value实例化Optional对象,若是value为空,则抛出空指针非常
*/
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
/**
* 经由value实例化Optional对象,若是value为空,则返回EMPTY,
* 若是value不为空,则挪用Optional::of(value)方式
*/
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
/**
* 若是value的值不为空,则返回value,不然抛出NoSuchElementException非常
*/
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
/**
* 若是value的值不为空,返回true,不然返回false
*/
public boolean isPresent() {
return value != null;
}
/**
* 若是value不为NULL,则使用value挪用消费者函数式接口的消费方式Consumer::accept()
*/
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
/**
* 若是存在值,而且值与给定谓词成家,则返回描述该值的值,不然返回空值
*/
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
/**
* 若是存在值,则将供应的映射函数应用于该值,若是究竟为非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));
}
}
/**
* 若是存在则返回值,不然返回其他给定的值
*/
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();
}
}
// other code....
}
empty()方式public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
若是明确透露一个持有NULL值的Optional实例,则使用Optional.empty()方式,例如:Optional nullOpt = Optional.empty();
of()方式public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
若是可以明确判断一个对象的值不为NULL时,应该使用Optional.of()方式,例如:User user = userService.findById(userId);
if(user != null){
Optional userOptional = Optional.of(user);
}
ofNullable()方式public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
若是无法确认一个对象的值是否为空的时候,应该使用Optional.ofNullable()方式,例如:User user = userService.findByEmail(userEmail);
Optional userOptional = Optional.ofNullable(user);
get()方式@NotNull
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
一样地,get()方式需要先确认value的值不为空后才使用,get()方式需要先校验value存在与否。例如:User user = userService.findByUsername(username);
if(user != null){
Optional userOptional = Optional.of(user);
User value = userOptional.get();
}
isPresent()方式public boolean isPresent() {
return value != null;
}
isPresent()方式用于判断value是否存在,若是存在,返回true;若是不存在,返回false。例如:User user = userService.findById(userId);
boolean exist = Optional.ofNullable(user).isPresent();
Optional<User> uop = userService.findOne(userId);
if(uop.isPresent()){
return uop.get();
}else{
return new User();
}
ifPresent()方式public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
顾名思义,若是value的值不为空,则使用value挪用消费者函数式接口的消费方式Consumer.accept(),例如:User user = userService.findById(userId);
Optional op = Optional.ofNullable(user);
op.ifPresent(u->System.out::println);
filter()方式public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
filter()方式用于实现简洁的过滤功能,若是Optional容器包含的值不为空,则返回知足过滤前提的值,不然返回empty()函数的返回值。例如:List<User> list = userService.findAll();
list.forEach(item->{
Optional.ofNullable(item)
.filter(user-> user.getStatus == 1)
.isPresent(user->System.out::println);
});
map()方式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));
}
}
map()方式用于类型转换把持,经由功能函数mapper.apply()对value进行类型映射,从新封装为可空的Optional对象实例,例如:List<String> list = Arrays.asList("java","jvm","jre","jdk");
Optional<List<String>> listOptional = Optional.of(list);
int size = listOptional.map(List::size).orElse(0);
System.out.println("size = " + size);
output:size = 4
flatMap()方式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));
}
}
与map()方式一般,flatMap()方式也是进行类型映射把持,独一分歧于map()方式的是flatMap()方式中Optional类型返回值直接由外部决意,不需要经由值从新封装为Optional实例。例如:public class User{
private String username;
public Optional<String> getUsername(){
return Optional.ofNullable(username);
}
public User(String username){
this.username = username;
}
}
public class TestFlatMapMethod{
public static void main(String[] args){
User user = new User("ramostear");
Optional<User> userOptional = Optional.of(user);
Optional<Optional<String>> usernameOptional = userOptional.map(User::getUsername);
//map()方式需要再次封装Optional类型
Optioanl<String> nameOptional = usernameOptional.orElseThrow(IllegalArgumentException::new);
String name = nameOptional.orElse("");
System.out.println(name);
//flatMap()方式不需要再次封装Optional类型
String username = userOptional.flatMap(User::getUsername).orElse("");
System.out.println(username);
}
}
orElse()方式public T orElse(T other) {
return value != null ? value : other;
}
orElse()方式的感化是:当value的值不存在时,供应一个默认的值,例如:String val1 = null;
String val2 = "default value";
String value = Optional.ofNullable(val1).orElse(val2);
String value2 = Optional.ofNullable(null).orElse("default value");
orElseGet()方式public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
orElseGet()方式是orElse()方式的升级版本,其优点是能够防止orElse()方式传入NULL值,例如:String val1 = null;
Supplier<String> fun = ()->"default value";
String value = Optional.ofNullable(val1).orElseGet(fun);
orElseThrow()方式public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
orElseThrow()方式相当于是orElse()方式和orElseGet()方式的增加版,供应了非常处理能力。需要注重的是,orElseThrow()方式处理非常时是抛出而不是捕捉。例如:String username = null;
String name = Optional.ofNullable(username).orElseThrow(IllegalArgumentException::new);
orElse()与orElseGet()的区别
对于不太熟悉Optional的法式员来说,orElse()方式和orElseGet()方式之间的区别并不显着,甚至会感觉这两个方式在功能上是重叠的。然而,这两个方式照样有着素质上的区别,若是不克很好的懂得个中的差别,使用这两个方式会严重影响到代码的运行机能。接下来,我们先看一个简洁的例子:public class OptionalExample {
public static void main(String[] args) {
String text = null;//"Hello Optional";
System.out.println("Using Optional.orElseGet() method...");
String value = Optional.ofNullable(text).orElseGet(OptionalExample::defaultValue);
System.out.println("orElseGet() method return value = " + value);
System.out.println("Using Optional.orElse() method...");
value = Optional.ofNullable(text).orElse(defaultValue());
System.out.println("orElse() method return value = " + value);
}
public static String defaultValue(){
System.out.println("Getting Default Value...");
return "Default Value";
}
}
defaultValue()方式用于返回默认的值,该方式不带任何恳求参数。变量text一起头的值为NULL,运行main方式并视察掌握台输出:"C:\Program Files\Java\jdk1.8.0_66\bin\java.exe"...
Using Optional.orElseGet() method...
Getting Default Value...
orElseGet() method return value = Default Value
Using Optional.orElse() method...
Getting Default Value...
orElse() method return value = Default Value
在变量text为NULL的情形下,orElse()方式和orElseGet()方式具有一致的感化,没有任何区别。接下来,将变量text的值点窜为“Hello Optional”,运行main方式并视察掌握台输出:"C:\Program Files\Java\jdk1.8.0_66\bin\java.exe"...
Using Optional.orElseGet() method...
orElseGet() method return value = Hello Optional
Using Optional.orElse() method...
Getting Default Value...
orElse() method return value = Hello Optional
当变量text有值的情形下,究竟发生了改变。使用orElseGet()方式来判断text的值时,defaultValue()方式不会被执行,因为text值不为空,但使用orElse()方式来判断text值时,无论text的值是否为空,defaultValue()方式都邑被执行,在这种情形下,defaultValue()方式就显得非常的冗余且影响代码机能。
为什么为发生如许的区别?原因在于orElse()方式需要供应一个类型变量,在orElse()方式工作之前,就需要确定类型变量的值,这也就是为什么在变量text有值的情形下defaultValue()方式依然被执行的原因;而orElseGet()方式的入参是对象的供应者(Supplier),只有当变量text为空的时候,才会挪用对象供应者所供应的具体方式。
总结
本文具体介绍了Java 8 Optional类的根基用法、注重事项以及区别。个中值得注重的是of(),ofNullable()之间的区别,get()的使用前提,map()和flatMap()的区别,orElse和orElseGet()的使用场景。