- 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权限的,不能由外部调用的。
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
其余三个函数是public权限,供我们所调用。
empty()Optional类内部还维护一个value为null的对象,大概就是长下面这样的:
public final class Optional{ //省略.... private static final Optional> EMPTY = new Optional<>(); private Optional() { this.value = null; } //省略... public static Optional empty() { @SuppressWarnings("unchecked") Optional t = (Optional ) EMPTY; return t; } }
empty() 的作用就是返回EMPTY对象。
of(T value)public staticOptional of(T value) { return new Optional<>(value); }
of(T value)函数内部调用了构造函数。根据构造函数的源码我们可以得出两个结论:
- 通过of(T value)函数所构造出的Optional对象,当Value值为空时,依然会报NullPointerException。
- 通过of(T value)函数所构造出的Optional对象,当Value值不为空时,能正常构造Optional对象。
使用场景:
当我们在运行过程中,不想隐藏NullPointerException。而是要立即报告,这种情况下就用Of函数。
public staticOptional 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源码如下:
public T orElse(T other) {
return value != null ? value : other;
}
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;
}
}
这两个函数的区别:
orElseThrow(Supplier exceptionSupplier)上面的测试可以发现。
当person值不为null时,orElse函数依然会执行creatPerson()方法,
而orElseGet函数并不会执行creatPerson()方法;
orElseThrow,就是value值为null时,直接抛一个异常出去:
publicmap(Function mapper)和flatMap(Function> mapper)T orElseThrow(Supplier extends X> exceptionSupplier) throws X { if (value != null) { return value; } else { throw exceptionSupplier.get(); } }
两个函数做的是转换值的操作:
public final class Optional{ //省略.... public Optional map(Function super T, ? extends U> mapper) { Objects.requireNonNull(mapper); if (!isPresent()) return empty(); else { return Optional.ofNullable(mapper.apply(value)); } } //省略... public Optional flatMap(Function super T, Optional> 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>。
示例1:
public class OptionalMapFilterDemo {
public static void main(String[] args) {
String password = "password";
Optional opt = Optional.ofNullable(password);
Predicate len6 = pwd -> pwd.length() > 6;
Predicate len10 = pwd -> pwd.length() < 10;
Predicate 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 getNickName() {
return Optional.ofNullable(nickName);
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
@Override
public 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;
});
}
采用这种链式编程,虽然代码优雅了。但是,逻辑性没那么明显,可读性有所降低,大家项目中看情况酌情使用。



