• java的jdk8新特性optional怎么样使用


    从 Java 8 引入的一个很有趣的特性是 Optional  类。Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException) —— 每个 Java 程序员都非常了解的异常

    我们从一个简单的用例开始。在 Java 8 之前,任何访问对象方法或属性的调用都可能导致 NullPointerException

    String isocode = user.getListNames().get(0).toUpperCase();
    如果我们需要确保不触发异常,就得在访问每一个值之前对其进行明确地检查
    if (user != null) {
        List lists = user.getListNames();
        if (lists != null) {
            String str  = lists.get(0);
            if (str != null) {
                String isocode = country.getIsocode();
                
            }
        }
    }

    你看到了,这很容易就变得冗长,难以维护
    Optional的对象可能包含值,也可能为空。你可以使用同名方法创建一个空的 Optional

     你可以使用  of() 和 ofNullable() 方法创建包含值的 Optional。两个方法的不同之处在于如果你把 null 值作为参数传递进去,of() 方法会抛出 NullPointerException

     访问 Optional 对象的值,使用get方法

    当我们使用optional方法的时候也可能会抛异常,所以在get之前要再判断一下

    @Test
    public void whenCheckIfPresent_thenOk() {
        User user = new User("john@gmail.com", "1234");
        Optional<User> opt = Optional.ofNullable(user);
        assertTrue(opt.isPresent());
    
        assertEquals(user.getEmail(), opt.get().getEmail());
    }



    检查是否有值的另一个选择是 ifPresent() 方法。该方法除了执行检查,还接受一个Consumer(消费者) 参数,如果对象不是空的,就对执行传入的 Lambda 表达式:

    opt.ifPresent( u -> assertEquals(user.getEmail(), u.getEmail()));

    这个例子中,只有 user 用户不为 null 的时候才会执行断言

     

    返回默认值

    Optional 类提供了 API 用以返回对象值,或者在对象为空的时候返回默认值。

    这里你可以使用的第一个方法是 orElse(),它的工作方式非常直接,如果有值则返回该值,否则返回传递给它的参数值:

    @Test
    public void whenEmptyValue_thenReturnDefault() {
        User user = null;
        User user2 = new User("anna@gmail.com", "1234");
        User result = Optional.ofNullable(user).orElse(user2);
    
        assertEquals(user2.getEmail(), result.getEmail());
    }

    这里 user 对象是空的,所以返回了作为默认值的 user2

    如果对象的初始值不是 null,那么默认值会被忽略:

    @Test
    public void whenValueNotNull_thenIgnoreDefault() {
        User user = new User("john@gmail.com","1234");
        User user2 = new User("anna@gmail.com", "1234");
        User result = Optional.ofNullable(user).orElse(user2);
    
        assertEquals("john@gmail.com", result.getEmail());
    }

    第二个同类型的 API 是 orElseGet() —— 其行为略有不同。这个方法会在有值的时候返回值,如果没有值,它会执行作为参数传入的 Supplier(供应者) 函数式接口,并将返回其执行结果:

    User result = Optional.ofNullable(user).orElseGet( () -> user2);


    转换值

    有很多种方法可以转换 Optional  的值。我们从 map() 和 flatMap() 方法开始。

    先来看一个使用 map() API 的例子:

    @Test
    public void whenMap_thenOk() {
        User user = new User("anna@gmail.com", "1234");
        String email = Optional.ofNullable(user)
          .map(u -> u.getEmail()).orElse("default@gmail.com");
    
        assertEquals(email, user.getEmail());
    }

    map() 对值应用(调用)作为参数的函数,然后将返回的值包装在 Optional 中。这就使对返回值进行链试调用的操作成为可能 —— 这里的下一环就是 orElse()

    相比这下,flatMap() 也需要函数作为参数,并对值调用这个函数,然后直接返回结果。

    下面的操作中,我们给 User 类添加了一个方法,用来返回 Optional

    public class User {    
        private String position;
    
        public Optional<String> getPosition() {
            return Optional.ofNullable(position);
        }
    
        //...
    }

    既然 getter 方法返回 String 值的 Optional,你可以在对 User 的 Optional 对象调用 flatMap() 时,用它作为参数。其返回的值是解除包装的 String 值:

    @Test
    public void whenFlatMap_thenOk() {
        User user = new User("anna@gmail.com", "1234");
        user.setPosition("Developer");
        String position = Optional.ofNullable(user)
          .flatMap(u -> u.getPosition()).orElse("default");
    
        assertEquals(position, user.getPosition().get());
    }


    过滤值

    除了转换值之外,Optional  类也提供了按条件“过滤”值的方法。

    filter() 接受一个 Predicate 参数,返回测试结果为 true 的值。如果测试结果为 false,会返回一个空的 Optional

    来看一个根据基本的电子邮箱验证来决定接受或拒绝 User(用户) 的示例:

    @Test
    public void whenFilter_thenOk() {
        User user = new User("anna@gmail.com", "1234");
        Optional<User> result = Optional.ofNullable(user)
          .filter(u -> u.getEmail() != null && u.getEmail().contains("@"));
    
        assertTrue(result.isPresent());
    }

    如果通过过滤器测试,result 对象会包含非空值。

    
    
    
     






















  • 相关阅读:
    setTimeOut 和 setInterval对比
    vue官方源码剖析
    Taro 总结
    地图相交
    vscode 配置文件
    redis持久化的几种方式
    推荐.Net、C# 逆向反编译四大工具利器
    【转】Java 通过JDBC连接Mysql数据库的方法和实例【图文说明】
    【摘】Oracle 11g EM安全证书问题无法访问的解决办法
    MySql 从SQL文件导入
  • 原文地址:https://www.cnblogs.com/niCong/p/14100174.html
Copyright © 2020-2023  润新知