前言
在进行日常Java开发中遇见NullPointerException已经算是家常便饭了,有些情况没有考虑到有可能出现空指针异常,尤其是新手,即使考虑到了也要使用if-else去判断是否为空,这样有时候会让代码看上去复杂一些.
现在Java8有了Optional之后,空指针的校验就变得非常的方便和简洁,下面我们就来看看Optional的用法.
一、Optional 类
Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
Optional 类的引入很好的解决空指针异常。
二、常用方法
// 判断Optional中的值是否不为空,不为空返回true,反之返回false
public boolean isPresent()
// 获取Optional中的值,如果值为空则抛出NoSuchElementException
public T get()
// 创建一个Optional<T>对象,如果传入的value为空则抛出NullPointerException
public static <T> Optional<T> of(T value)
// 创建一个Optional<T>对象,如果传入的value为空则返回一个空的Optional对象(new Optional<>())
public static <T> Optional<T> ofNullable(T value)
// 判断Optional中的值是否为空,不为空则返回值,为空则返回传入的值other
public T orElse(T other)
// 判断Optional中的值是否为空,不为空则返回值,为空则抛出传入的异常
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X
//如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果
public T orElseGet(Supplier<? extends T> other)
// 如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional
public<U> Optional<U> map(Function<? super T, ? extends U> mapper)
三、常用方法应用
首先我们需要创建一个实体类,比如User.java
@Entity
@Table(name="user")
@Data
public class User{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String userName;
private String password;
private Integer sex;
@Column(name="last_login_time")
private Date lastLoginTime;
@Override
public String toString() {
return "admin{" +
"id=" + id +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
", sex=" + sex +
", lastLoginTime=" + lastLoginTime +
'}';
}
}
通常情况下我们写的判断传入参数是否为空的方法是这样子,比如我们要返回此用户的name。如果按传统的写法就会非常的冗余,阅读性较差。
public String GetNameTest(User user){
if(user==null){
return "This user does not exist ";
}else{
if (user.getUserName() == null || user.getName().isEmpty())
return "This username is null ";
else
return user.getUserName();
}
}
使用Optional之后一切就变得很方便简洁了,可读性也提高了。
Optional.ofNullable(user)
.map(temp -> temp.getUserName())
/*.map(new Function<User,String>(){// temp -> temp.getUserName()
@Override
public String apply(admin s) {
return s.getUserName();
})*/
.orElseThrow(() -> new NullPointerException("user or userName is null"));
/*.orElseThrow(new Supplier<NullPointerException>() {
@Override
public NullPointerException get() {
return new NullPointerException("user or userName is null");
}
})*/
此处补充一些Java 8另一个新特性Lambda 表达式,也可称为闭包。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
语法规则为:
**(parameters) -> expression
或
(parameters) ->{ statements; }**
简单举例:
// 1. 不需要参数,返回值为 5
() -> 5
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
看到这里相信大家对上一代码片段有一定层度的理解了,这里为了方便大家一起学习,小编将lambda学习教程之一的链接提供给大家。
下面我们看一下这三个函数的源码并进行分析
private final T value;
private static final Optional<?> EMPTY = new Optional<>();
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
public static<T> Optional<T> empty() {
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
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 <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
ofNullable():调用ofNullable()的时候会对传入的value值进行空验证,如果不为空则调用of()方法使用value值创建一个Optional对象,如果为空则new一个空的Optional;
map():调用map()方法的时候也会对value进行空验证,如果不为空则进行后面的操作,如果为空则同样new一个空的Optional;
orElseThrow():调用orElseThrow()方法的时候也会对value进行空验证,如果不为空则返回对应的值,如果为空则抛出一个传入的异常。