转载整理自:作者:孤独烟 出处: 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权限的,不能由外部调用
java8新特性-Optional

(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("[email protected]");;
    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

相关文章: