文章目录
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;
}
@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;
});
}
采用这种链式编程,虽然代码优雅了。但是,逻辑性没那么明显,可读性有所降低,大家项目中看情况酌情使用。