Optional

        从 Java 8 引入的一个很有趣的特性是 Optional  类。Optional 类主要解决的问题是臭名昭著的空指针异常

       本质上,这是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空。

public final class Optional<T> {
    /**
     * Common instance for {@code empty()}.
     */
    private static final Optional<?> EMPTY = new Optional<>();

    /**
     * If non-null, the value; if null, indicates no value is present
     */
    private final T value;

    /**
     * Constructs an empty instance.
     *
     * @implNote Generally only one empty instance, {@link Optional#EMPTY},
     * should exist per VM.
     */
    private Optional() {
        this.value = null;
    }
}

通过源码分析 ,Optional是一个final类,

  • 说明不能被继承

  • 它的构造函数是私有的,是单列的对象

  • 提供一系列的方法,对其java程序逻辑的判断和优化处理

主要方法如下:

of:为非null的值创建一个Optional。of方法通过工厂方法创建Optional类。需要注意的是,创建对象时传入的参数不能为null。如果传入参数为null,则抛出NullPointerException。因此不经常用。
ofNullable:为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。
isPresent:如果值存在返回true,否则返回false。
ifPresent:如果Optional实例有值则为其调用consumer,否则不做处理
get:如果Optional有值则将其返回,否则抛出NoSuchElementException。因此也不经常用。
orElse:如果有值则将其返回,否则返回指定的其它值。
orElseGet:orElseGet与orElse方法类似,区别在于得到的默认值。orElse方法将传入的字符串作为默认值,orElseGet方法可以接受Supplier接口的实现用来生成默认值
orElseThrow:如果有值则将其返回,否则抛出supplier接口创建的异常。
filter:如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional。
map:如果有值,则对其执行调用mapping函数得到返回值。如果返回值不为null,则创建包含mapping返回值的Optional作为map方法返回值,否则返回空Optional。
flatMap:如果有值,为其执行mapping函数返回Optional类型返回值,否则返回空Optional

1.of和ofNullable 初始化Optional对象

User user = userservice.getId("1");
Optional<User> optional = Optional.ofNullable(user);
Optional<User> optional1 = Optional.of(user);

两个方法的不同之处在于如果你把 null 值作为参数传递进去,of() 方法会抛出 NullPointerException:

of方法的底层有一个这个方法

public static <T> T requireNonNull(T obj) {
    if (obj == null)
        throw new NullPointerException();
     return obj;
}

应该明确对象不为 null  的时候使用 of()。

如果对象即可能是 null 也可能是非 null,你就应该使用 ofNullable() 方法:

2.isPresent()方法  如果为空就返回false

 isPresent()方法的源码:

    public boolean isPresent() {
        return value != null;
    }

isPresent()方法用于判断包装对象的值是否非空 

User user = null;
//上面那个user相当于从数据库查询
//User user = userService.getUser(id)
Optional<User> optionalUser = Optional.ofNullable(user);
if (!optionalUser.isPresent()){
    System.out.println("用户找不到");
}

//简化为
User user1 = Optional.ofNullable(user).orElseThrow(() -> new RuntimeException("用户找不到")); 

 user对象是null。所以optional.isPresent()结果就是false。所以出现异常

3.orElse()方法 有值则返回该值,否则返回传递给它的参数值

orElse()方法的源码:

    public T orElse(T other) {
        return value != null ? value : other;
    }

包装对象值非空,返回包装对象值,否则返回入参other的值 

User user =null;
//可以达到赋默认值
User user2 = Optional.ofNullable(user).orElse(new User());
//这个时候user2对象不为空,只不过里面属性的值为空
User zzz = Optional.ofNullable(user2).orElse(new User(1, "zzz", "111"));
System.out.println("zzz="+zzz);

user2.setUsername(Optional.ofNullable(user2.getUsername()).orElse("liang"));
user2.setPassword(Optional.ofNullable(user2.getPassword()).orElse("123456"));
System.out.println("user2="+user2);


//输出结果
zzz=User{id=null, username=null, password=null}
user2=User{id=null, username='liang', password='123456'}

如上面例子,当user对象为空时,就会new一个对象赋值给user2,当user2不为空时,拿的还是user2的原先的值(new User() )赋值给zzz。

4.orElseGet()方法 在有值的时候返回值,如果没有值,它会执行作为参数传入的 Supplier(供应者) 函数式接口,并将返回其执行结果

orElseGet()方法的源码:

    public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
    }

orElseGet()方法与orElse()方法类似,区别在于orElseGet()方法的入参为一个Supplier对象,用Supplier对象的get()方法的返回值作为默认值。 

 User user3 = Optional.ofNullable(user).orElseGet(() -> {
            //可以加各种处理逻辑
       User user1 = new User();
       user1.setUsername("zhangsan");
       return user1;
});

5.orElseGet()方法orElse()方法 的区别

        乍一看,这两种方法似乎起着同样的作用。然而事实并非如此。我们创建一些示例来突出二者行为上的异同。

        先看对象不为空的情况

  public static void main(String[] args){
        List<Integer> list = Arrays.asList(23,1,3);
        int myElse = list.stream().reduce(Integer::sum).orElse(get("myElse"));
        int myElseGet = list.stream().reduce(Integer::sum).orElseGet(() -> get("myElseGet"));

        System.out.println("myElse的值"+myElse);
        System.out.println("myElseGet的值"+myElseGet);

    }
    public static int get(String name){
        System.out.println(name+"执行了该方法");
        return 1;
    }


//输出结果
myElse执行了该方法
myElse的值27
myElseGet的值27

 对象为空的情况

   public static void main(String[] args){
        List<Integer> list = Arrays.asList();
        int myElse = list.stream().reduce(Integer::sum).orElse(get("myElse"));
        int myElseGet = list.stream().reduce(Integer::sum).orElseGet(() -> get("myElseGet"));
        System.out.println("myElse的值"+myElse);
        System.out.println("myElseGet的值"+myElseGet);

    }
    public static int get(String name){
        System.out.println(name+"执行了该方法");
        return 1;
    }

从上面optional为空值和有值的情况的例子可以看到orElse在不论optional有没有值的时候都会执行,在optional为空值的情况下orElse和orElseGet都会执行,当optional不为空时,orElseGet不会执行。

 6.orElseThrow 它会在对象为空的时候抛出异常,而不是返回备选的值

orElseThrow()方法的源码:

    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }

orElseThrow()方法其实与orElseGet()方法非常相似了,入参都是Supplier对象,只不过orElseThrow()的Supplier对象必须返回一个Throwable异常,并在orElseThrow()中将异常抛出:

User user1 = Optional.ofNullable(user).orElseThrow(() -> new RuntimeException("用户找不到"));

如果user为null,就会抛出异常。这个方法让我们有更丰富的语义,可以决定抛出什么样的异常,而不总是抛出 NullPointerException

7.map()方法

        源码为

    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));
        }
    }

map()方法的参数为Function(函数式接口)对象,map()方法将Optional中的包装对象用Function函数进行运算,并包装成新的Optional对象(包装对象的类型可能改变)。举例如下:

    public static Optional<Integer> getAge(Student student){
        return Optional.ofNullable(student).map(u -> u.getAge()); 
    }

上述代码中,先用ofNullable()方法构造一个Optional<Student>对象,然后用map()计算学生的年龄,返回Optional<Integer>对象(如果student为null, 返回map()方法返回一个空的Optinal对象)。

8.flatMap

  flatMap()方法的源码:

    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函数的返回值类型为Optional<U>类型,而不是U类型,这样flatMap()能将一个二维的Optional对象映射成一个一维的对象。以map方法中示例功能为例,进行faltMap()改写如下:

    public static Optional<Integer> getAge(Student student){
        return Optional.ofNullable(student).flatMap(u -> Optional.ofNullable(u.getAge())); 
    }

map和flatMap示例

  User user = new User(1,"zhang_san","123456");
        Optional<String> username = Optional
                .ofNullable(user)
                .map(user1 -> user1.getUsername())
                .map(new Function<String, String>() {
                    @Override
                    public String apply(String s) {
                        System.out.println("s=="+s);
                         s = s + "你好啊";
                        return s;
                    }
                })
                ;

  System.out.println("Username is: " + username.orElse("Unknown"));

//输出结果
s==zhang_san
Username is: zhang_san你好啊

map他会把值传到下一个map对值进行处理,可以多次进行处理

Optional<String> username = Optional
        .ofNullable(getUserById(id))
        .map(user -> user.getUsername())
        .map(name -> name.toLowerCase())
        .map(name -> name.replace('_', ' '));
        
System.out.println("Username is: " + username.orElse("Unknown"));

flatmap:

Optional<String> username = Optional
        .ofNullable(getUserById(id))
        .flatMap(user -> Optional.of(user.getUsername()))
        .flatMap(name -> Optional.of(name.toLowerCase()));
        
System.out.println("Username is: " + username.orElse("Unknown"));

9. filter()方法

 filter()方法的源码:

    public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
    }

filter()方法接受参数为Predicate对象,用于对Optional对象进行过滤,如果符合Predicate的条件,返回Optional对象本身,否则返回一个空的Optional对象。举例如下

    public static void filterAge(Student student){
        Optional.ofNullable(student).filter( u -> u.getAge() > 18).ifPresent(u ->  System.out.println("The student age is more than 18."));
    }

参考:https://www.jianshu.com/p/790f7c185d3e

https://www.oschina.net/translate/understanding-accepting-and-leveraging-optional-in

https://www.jianshu.com/p/d81a5f7c9c4e

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值