Java8 Optional类用法
文章目录
- API介绍
- 第一组
- Optional(T value)
- empty()
- of(T value)
- ofNullable(T value)
- 第二组
- orElse(T other),orElseGet(Supplier other)
- orElseThrow(Supplier exceptionSupplier)
- map(Function mapper)和flatMap(Function> mapper)
- isPresent()和ifPresent(Consumer consumer)
- filter(Predicate predicate)
- 案例
- 例子1
- 例子2
- 例子3
Java8 提供了Optional类来优化判空写法。
Optional的本质,就是内部储存了一个真实的值,在构造的时候,就直接判断其值是否为空。
API介绍
第一组
这四个函数之间具有相关性,因此放在一起;
Optional(T value)
Optional(T value),即构造函数,它是private
权限的,不能由外部调用的。
/*** Constructs an instance with the described value.** @param value the non-{@code null} value to describe* @throws NullPointerException if value is {@code null}*/private Optional(T value) {this.value = Objects.requireNonNull(value);}
其余三个函数是public权限,供我们所调用。
empty()
Optional类内部还维护一个value为null的对象,大概就是长下面这样的:
public final class Optional<T> {//省略....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;}
}
empty() 的作用就是返回EMPTY对象。
of(T value)
public static <T> Optional<T> of(T value) {return new Optional<>(value);
}
of(T value)函数内部调用了构造函数。根据构造函数的源码我们可以得出两个结论:
- 通过of(T value)函数所构造出的Optional对象,当Value值为空时,依然会报NullPointerException。
- 通过of(T value)函数所构造出的Optional对象,当Value值不为空时,能正常构造Optional对象。
使用场景:
当我们在运行过程中,不想隐藏NullPointerException。而是要立即报告,这种情况下就用Of函数。
ofNullable(T value)
public static <T> Optional<T> ofNullable(T value) {return value == null ? empty() : of(value);
}
相比较of(T value)的区别就是:
当value值为null时,of(T value)会报NullPointerException异常;ofNullable(T value)不会throw Exception,ofNullable(T value)直接返回一个EMPTY对象。
第二组
这三个函数放一组进行记忆,都是在构造函数传入的value值为null时,进行调用的。
orElse(T other),orElseGet(Supplier other)
详细API源码如下:
/*** Return the value if present, otherwise return {@code other}.** @param other the value to be returned if there is no value present, may* be null* @return the value, if present, otherwise {@code other}*/
public T orElse(T other) {return value != null ? value : other;
}/*** Return the value if present, otherwise invoke {@code other} and return* the result of that invocation.** @param other a {@code Supplier} whose result is returned if no value* is present* @return the value if present otherwise the result of {@code other.get()}* @throws NullPointerException if value is not present and {@code other} is* null*/
public T orElseGet(Supplier<? extends T> other) {return value != null ? value : other.get();
}
orElse和orElseGet的用法如下所示,相当于value值为null时,给予一个默认值:
public class OptionalTest {public static void main(String[] args) throws Exception {// Person person = null;Person person = new Person();Person person1 = Optional.ofNullable(person).orElse(creatPerson());System.out.println(person1);Person person2 = Optional.ofNullable(person).orElseGet(() -> creatPerson());System.out.println(person2);Optional.ofNullable(person).orElseThrow(() -> new Exception("没有此人"));}public static Person creatPerson() {Person person = new Person();person.setName("Tom");person.setAge(18);person.setNickName("cat");System.out.println("create person");return person;}
}
这两个函数的区别:
上面的测试可以发现。
当person值不为null时,orElse函数依然会执行creatPerson()方法,
而orElseGet函数并不会执行creatPerson()方法;
orElseThrow(Supplier exceptionSupplier)
orElseThrow,就是value值为null时,直接抛一个异常出去:
/*** Return the contained value, if present, otherwise throw an exception* to be created by the provided supplier.** @apiNote A method reference to the exception constructor with an empty* argument list can be used as the supplier. For example,* {@code IllegalStateException::new}** @param <X> Type of the exception to be thrown* @param exceptionSupplier The supplier which will return the exception to* be thrown* @return the present value* @throws X if there is no value present* @throws NullPointerException if no value is present and* {@code exceptionSupplier} is null*/
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {if (value != null) {return value;} else {throw exceptionSupplier.get();}
}
map(Function mapper)和flatMap(Function> mapper)
两个函数做的是转换值的操作:
public final class Optional<T> {//省略....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<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函数所接受的入参类型为Function<? super T, ? extends U>,
而flapMap的入参类型为Function<? super T, Optional<U>>。
示例1:
public class OptionalMapFilterDemo {public static void main(String[] args) {String password = "password";Optional<String> opt = Optional.ofNullable(password);Predicate<String> len6 = pwd -> pwd.length() > 6;Predicate<String> len10 = pwd -> pwd.length() < 10;Predicate<String> eq = pwd -> pwd.equals("password");boolean result = opt.map(String::toLowerCase).filter(len6.and(len10 ).and(eq)).isPresent();System.out.println(result);}
}
示例2:
public class Person {private String name;private int age;private String nickName;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Optional<String> getNickName() {return Optional.ofNullable(nickName);}public void setNickName(String nickName) {this.nickName = nickName;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", nickName='" + nickName + '\'' +'}';}
}
public static void testMap() {Person newPerson = creatPerson();Integer age = Optional.ofNullable(newPerson).map(e -> e.getAge()).get();System.out.println("newPerson age = " + age);String nickName = Optional.ofNullable(newPerson).flatMap(e -> e.getNickName()).get();System.out.println("newPerson nickName = " + nickName);
}
isPresent()和ifPresent(Consumer consumer)
这两个函数放在一起记忆,isPresent即判断value值是否为空,而ifPresent就是在value值不为空时,做一些操作。
filter(Predicate predicate)
filter 方法接受一个 Predicate 来对 Optional 中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个 Optional;否则返回 Optional.empty。
案例
例子1
比如,在主程序中
以前写法
if(user!=null){dosomething(user);
}
java8写法
Optional.ofNullable(user).ifPresent(u->{dosomething(u);
});
例子2
在函数方法中
以前写法
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("取指错误"));
}
例子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;});
}
采用这种链式编程,虽然代码优雅了。但是,逻辑性没那么明显,可读性有所降低,大家项目中看情况酌情使用。
Java8 Optional类用法相关推荐
- 新容器!不再担心空指针, Java8 Optional类
Optional<T>类(java.util.Optional)是一个容器类,它可以保存类型T的值,代表这个值存在.或者仅仅保存null,表示这个值不存在.原来用 null 表示一个值不存 ...
- Java8 Optional类
概述 到目前为止,著名的NullPointerException是导致Java应用程序失败的最常见原因.过去,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guav ...
- Java8新特性Optional类
这里写自定义目录标题 Java8 Optional 类 前言 创建 Optional 实例 Optional API常用接口的用法 get()方法 isPresent()方法 isPresent()方 ...
- Java8新特性 Optional类
作为开发人员每天与NullPointerException斗智斗勇.每接收到参数或调用方法获得值得判断一下是否为null.稍不留意,空指针异常就像幽灵一样出现了.这篇文章我们来学习Java8是如何通过 ...
- Java8新特性学习_001_(Lambda表达式,函数式接口,方法引用,Stream类,Optional类)
目录 ■代码 ■代码运行结果 ■代码说明 ・44行:Stream的.foreach方法ー参数类型:函数式接口 ・82行:Interface中,default方法 ・92行 Stream的.max方 ...
- Java8新特性之空指针异常的克星Optional类
Java8新特性系列我们已经介绍了Stream.Lambda表达式.DateTime日期时间处理,最后以"NullPointerException" 的克星Optional类的讲解 ...
- 如何正确的使用Java8中的Optional类来消除代码中的null检查
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:一书生VOID lw900925.github.io/jav ...
- 学习笔记之-java8的新特性-函数式接口,lambda表达式,方法引用,Stream API,Optional类
1.Lambda表达式 用匿名内部类的方法去创建多线程1.new Thread2.参数传递new Runnable3.重写run方法4.在run方法中去设置线程任务5.调用start问题:我们最终目标 ...
- java8新特性(5)— Optional 类
java8新特性(5)- Optional 类 空指针解决方案 package com.common.jdk8;import java.util.Optional;//Optional 类是一个可以为 ...
最新文章
- Set 、HashSet、TreeSet、LinkedHashSet、EnumSet
- bert简介_关于BERT:你不知道的事
- matlab parfor不能用,matlab中parfor函数
- mysql遇到时区问题的坑(Java解决方案)
- 实现IButtonControl接口时, PerformClick()方法的代码怎么写,请高手指导!
- android开发ui插件下载,TKUISDK-ANDROID
- 百度编辑器回显js报错Uncaught SyntaxError: Invalid or unexpected token
- SpringCloud学习笔记028---在SpringBoot中整合多数据源_实战项目
- c语言父 app,90后父母最爱的10款实用APP,中老年人必备!
- 用Visio画UML顺序图
- 141个关于人工智能的统计数据
- 【LaTex】6.4 listings高亮设置
- 视频号直播间微信小程序开发制作介绍
- 华为的服务器虚拟化软件,服务器虚拟化软件
- 艾默生质量流量计调试
- CentOS7安装onlyoffice实现word的在线预览和编辑
- 什么是集合,集合和数组的区别是什么
- MBR与GPT分区的区别及使用注意事项(转载)
- Hive性能优化(全面)解决数据倾斜等问题
- 碎影录·Freshman In SDU by郝宗铎