转载整理自:作者:孤独烟 出处: http://rjzheng.cnblogs.com/
调用示例
optional是java8的一个新特性,通过这个类我们可以优雅的解决 NullPointException 的问题,避免了大量的为空判断
先给几个例子
1、
旧写法:
public String getCity(User user) throws Exception{
if(user!=null){
if(user.getAddress()!=null){
Address address = user.getAddress();
if(address.getCity()!=null){
return address.getCity();
}
}
}
throw new Excpetion("取值错误");
}
java8:
public String getCity(User user) throws Exception{
return Optional.ofNullable(user)
.map(u-> u.getAddress())
.map(a->a.getCity())
.orElseThrow(()->new Exception("取指错误"));
}
2、
旧写法:
if(user!=null){
dosomething(user);
}
java8:
Optional.ofNullable(user)
.ifPresent(u->{
dosomething(u);
});
3、
旧写法:
public User getUser(User user) throws Exception{
if(user!=null){
String name = user.getName();
if("zhangsan".equals(name)){
return user;
}
}else{
user = new User();
user.setName("zhangsan");
return user;
}
}
java8:
public User getUser(User user) {
return Optional.ofNullable(user)
.filter(u->"zhangsan".equals(u.getName()))
.orElseGet(()-> {
User user1 = new User();
user1.setName("zhangsan");
return user1;
});
}
4、optional不为空返回object,为空返回null
Tally tally = tallyRepository.findById((long) 99).orElse(null);//orElseGet提示异常
if(tally != null){
System.out.println(tally.getRemarks());
}
1、Optional(T value),empty(),of(T value),ofNullable(T value)
(1)Optional(T value)
构造函数,它是private权限的,不能由外部调用
(2)empty()
返回一个空的 Optional 实例
源码:(Optional类内部还维护一个value为null的对象)
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;
}
(3)of(T value)
返回一个指定非null值的Optional,当Value值为空时,会报NullPointerException异常
源码:
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
(4)ofNullable(T value)
如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional
源码:
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
(5)of(T value)与ofNullable(T value)区别
当传入的value值为null时,of(T value)会报空指针(NullPointerException)异常;ofNullable(T value)不会抛出空指针异常而会直接返回一个EMPTY对象。当我们在运行过程中,不想隐藏空指针异常而是要立刻抛出则使用Of函数
2、orElse(T other),orElseGet(Supplier<? extends T> other)和orElseThrow(Supplier<? extends X> exceptionSupplier)
(1)T orElse(T other):如果存在该值,返回值, 否则返回 other
(2)T orElseGet(Supplier<? extends T> other):如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果
(3) T orElseThrow(Supplier<? extends X> exceptionSupplier):如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常
测试代码:
@Test
public void test() {
User user1 = null;
try {
Optional.ofNullable(user1).orElseThrow(()->new Exception("用户不存在"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
User user2 = null;
user2 = Optional.ofNullable(user2).orElse(createUser());
System.out.println(user2.getEmail());
User user3 = null;
user3 = Optional.ofNullable(user3).orElseGet(() -> createUser());
System.out.println(user3.getEmail());
}
public User createUser(){
User user = new User();
user.setEmail("764682881@qq.com");;
return user;
}
orElse(T other)和orElseGet的区别:当user值不为null时,orElse函数依然会执行createUser()方法,而orElseGet函数并不会执行createUser()方法,由于orElseGet()不是每次都会调用传入的方法,所以orElseGet()方法在性能上要优于orElse()方法,orElseThrow则是当值为null时,直接抛一个异常
3、map(Function<? super T, ? extends U> mapper)和flatMap(Function<? super T, Optional> mapper)
(1)map(Function<? super T, ? extends U> mapper):如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optiona
源码:
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));
}
}
(2)flatMap(Function<? super T, Optional> mapper):如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional
源码:
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函数所接受的入参类型为Function<? super T, ? extends U>,而flapMap的入参类型为Function<? super T, Optional>,即Map入参方法返回的参数是对象,flatMap入参方法返回的是Optional
调用:
<1>user结构为:
public class User {
private String name;
public String getName() {
return name;
}
}
使用map
String city = Optional.ofNullable(user).map(u-> u.getName()).get();
<2>user结构为:
public class User {
private String name;
public Optional<String> getName() {
return Optional.ofNullable(name);
}
}
使用flatMap
String city = Optional.ofNullable(user).flatMap(u-> u.getName()).get();
**
4、isPresent()和ifPresent(Consumer<? super T> consumer)
**
isPresent即判断value值是否为空,而ifPresent就是在value值不为空时,做一些操作。这两个函数的源码如下
注意:最好不要把
if (user != null){
// TODO: do something
}
写成:
User user = Optional.ofNullable(user);
if (Optional.isPresent()){
// TODO: do something
}
这种写法Optional就丧失了意义
public final class Optional<T> {
//省略....
public boolean isPresent() {
return value != null;
}
//省略...
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
}
ifPresent(Consumer<? super T> consumer),用法如下所示
Optional.ofNullable(user).ifPresent(u->{
// TODO: do something
});
5、filter(Predicate<? super T> predicate)
filter 方法接受一个 Predicate 来对 Optional 中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个 Optional;否则返回 Optional.empty
源码:
public final class Optional<T> {
//省略....
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
用法示例:
Optional<User> user1 = Optional.ofNullable(user).filter(u -> u.getName().length()<6);
如上所示,如果user的name的长度是小于6的,则返回。如果是大于6的,则返回一个EMPTY对象。
6、get()
T get():如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException