Java基础之Optional类(JDK1.8新特性)

简介: Optional是一个容器,它可以保存类型T的值,或者仅仅保存null,Optional类主要是用来避免空指针异常(NPE),其提供的一系列的方法配合Lambda表达式可以让代码更加清晰,语义化,以及避免了空指针异常的问题,这里要注意是避免空指针异常,而不是避免返回null。

定义

Optional是一个容器,它可以保存类型T的值,或者仅仅保存null,Optional类主要是用来避免空指针异常(NPE),其提供的一系列的方法配合Lambda表达式可以让代码更加清晰,语义化,以及避免了空指针异常的问题,这里要注意是避免空指针异常,而不是避免返回null。

Optional方法的使用

1.empty 方法返回一个不包含值的Optional实例,注意不保证返回的empty是单例,不要用==比较。

public static<T> Optional<T> empty()

2.of 方法返回一个Optional实例,传入的值必须是非空值,传入null会抛出空指针异常。

public static <T> Optional<T> of(T value)

3.返回一个Optional实例,如果传入值非空,则实例中包含非空值,如果传入null,返回不包含值的empty

public static <T> Optional<T> ofNullable(T value)

4.isPresent 方法用来判断实例是否包含值,如果不包含非空值返回false,否则返回true

public boolean isPresent();

5.get方法,如果实例包含值则返回当前值,否则抛出NoSushElementException 异常.

public T get();

不推荐调用上面两个方法,因为容易写出如下代码,比原先判断if null的代码还要脏

public static String getUserName1(User user) {
        Optional<User> user1 = Optional.ofNullable(user);
        if (!user1.isPresent()) {
            return "参数为空";
        }
        return user1.get().getName();
    }

下面是用if-null

public static String getUserName(User user) {
        if (user == null) {
            return "参数为空";
        }
        return user.getName();
    }

ifPresent(Consumer consumer):如果option对象保存的值不是null,则调用consumer对象,否则不调用

public void ifPresent(Consumer<? super T> consumer);

代码示例:

Optional<Integer> optional1 = Optional.ofNullable(1);
        Optional<Object> optional2 = Optional.ofNullable(null);
     //如果不是null,调用Consumer
        optional1.ifPresent(t -> System.out.println("value is" + t));   //value is1
        //如果是null,不调用Consumer
        optional2.ifPresent(t -> System.out.println("value is " + t));

如上代码,输出结果是 第一条 语句输出value is1,第二条语句没有输出

7. filter方法如果值存在,并且这个值匹配给定的predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional

Optional<T> filter(Predicate<? super <T> predicate)

代码示例:

Optional<Integer> optional1 = Optional.ofNullable(1);
       Optional<Object> optional2 = Optional.ofNullable(null);
       Optional<Integer> filter1 = optional1.filter(a -> a == null);
        Optional<Integer> filter2 = optional1.filter((a) -> a == 1);
        Optional<Object> filter3 = optional2.filter(a -> a == null);
    System.out.println(filter1.isPresent()); //false
        System.out.println(filter2.isPresent()); //true
        System.out.println(filter2.get().intValue() == 1); //true
        System.out.println(filter3.isPresent()); //false

如上代码,演示了filter方法如何使用,输出结果如代码注释所示。

8. map(Function):对Optional中保存的值进行函数运算,并返回新的Optional(可以是任何类型)

public<U> Optional<U> map(Function<? super T, ? extends U> mapper);

代码示例:输出结果已经写在注释中。

Optional<Integer> optional1 = Optional.ofNullable(1);
        Optional<Object> optional2 = Optional.ofNullable(null);
  Optional<String> str1Optional = optional1.map(a -> "key" + a);
        Optional<String> str2Optional = optional2.map(a -> "key" + a);
        System.out.println(str1Optional.get()); //key1
        System.out.println(str2Optional.isPresent()); //false

flatMap():功能与map()相似,差别在返回值不同,flatMap方法的mapping函数返回值可以是任何类型T,而map方法的mapping函数必须是Optional

public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper);

代码示例:

Optional<Integer> optional1 = Optional.ofNullable(1);
        Optional<Object> optional2 = Optional.ofNullable(null);
       Optional<Optional<String>> str11Optional = optional1.map(a -> Optional.of("key" + a));
        Optional<String> str22Optional = optional1.flatMap(a -> Optional.of("key" + a));
        System.out.println(str11Optional.get().get()); //key1
        System.out.println(str22Optional.get()); //key1

orElse方法,如果optional对象保存的值不是null,则返回原来的值,否则返回value。

public T orElse(T other);

代码示例:

Optional<Integer> optional1 = Optional.ofNullable(1);
        Optional<Object> optional2 = Optional.ofNullable(null);
    System.out.println(optional1.orElse(1000) == 1); //true
        System.out.println((Integer) optional2.orElse(1000) == 1000);//true
orElseGet(Supplier supplier):功能与orElse一样,只不过orElseGet参数是一个对象。
  public T orElseGet(Supplier<? extends T> other);

代码示例:

Optional<Integer> optional1 = Optional.ofNullable(1);
        Optional<Object> optional2 = Optional.ofNullable(null);
   System.out.println(optional1.orElseGet(() -> 1000) == 1); //true
        System.out.println((Integer) optional2.orElseGet(() -> 1000) == 1000); //true

orElseThrow方法,值不存在则调用传入的Supplier参数,生成一个异常实例并抛出,这个方法通常与全局异常处理器一起使用,当参数或者其他情况获取不到值是,抛出自定义异常,由异常处理器处理成通用返回结果。

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier);

代码示例:

optional1.orElseThrow(() -> {
            throw new IllegalStateException();
        });
        try {
            optional2.orElseThrow(() -> {
                throw new IllegalStateException();
            });
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }

实战参考

假设我们要解析一段json字符串,按照传统的if-null方式我们需要做如下处理:为了获取CUid的值,我们必须要判断三次。

public static String getOrgUid(String orgResult) {
        if (StringUtils.isBlank(orgResult)) {
            return null;
        }
        JSONObject jsonObject = JSON.parseObject(orgResult);
        if (jsonObject == null) {
            return null;
        }
        if ("success".equals(jsonObject.getString("result"))) {
            return jsonObject.getString("CUid");
        }
        return null;
    }

而运用了我们的Optional类之后,我们可以通过函数式变成来实现。

public static String getNewUid(String orgResult) {
        String orElse = Optional.ofNullable(orgResult)
                .map(n -> JSONObject.parseObject(n))
                .map(a -> {
                    if ("success".equals(a.getString("result"))) {
                        return a.getString("CUid");
                    }
                    return null;
                }).orElse(null);
        return orElse;
    }

运用了函数式变成,我们只需要三段3段代码就能轻松的驾驭,代码简洁明了。

总结

本文主要介绍了Optional类的一些常用方法,以及其应用场景,其主要是为了规避空指针异常(NPE)。熟练的运用Optional类可以很大的简化我们的代码,使代码简洁明了。

参考

JDK8 Optional 应用场景与方式分析

Java 8 Optional 类

JDK8新特性:使用Optional

相关文章
|
4天前
|
Java 关系型数据库 MySQL
Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
【4月更文挑战第12天】Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
29 3
|
23小时前
|
安全 Java 大数据
探索Java的奇妙世界:语言特性与实际应用
探索Java的奇妙世界:语言特性与实际应用
|
1天前
|
Java
【Java基础】详解面向对象特性(诸如继承、重载、重写等等)
【Java基础】详解面向对象特性(诸如继承、重载、重写等等)
5 0
|
1天前
|
安全 Java 程序员
|
2天前
|
Java Linux Shell
【Linux】bash: /home/stefan/jdk1.7.0_55/bin/java: /lib/ld-linux.so.2: bad ELF interpreter
【Linux】bash: /home/stefan/jdk1.7.0_55/bin/java: /lib/ld-linux.so.2: bad ELF interpreter
9 0
|
2天前
|
Java
Java Class类
Java Class类
8 0
|
7天前
|
机器学习/深度学习 Java API
Java8中的新特性
Java8中的新特性
|
9天前
|
Java 编译器
Java Character 类
4月更文挑战第13天
|
9天前
|
Oracle Java 关系型数据库
Java 开发者必备:JDK 版本详解与选择策略(含安装与验证)
Oracle Java SE 支持路线图显示,JDK 8(LTS)支持至2030年,非LTS版本如9-11每6个月发布且支持有限。JDK 11(LTS)支持至2032年,而JDK 17及以上版本现在提供免费商用许可。LTS版本提供长达8年的支持,每2年发布一次。Oracle JDK与OpenJDK有多个社区和公司构建版本,如Adoptium、Amazon Corretto和Azul Zulu,它们在许可证、商业支持和更新方面有所不同。个人选择JDK时,可考虑稳定性、LTS、第三方兼容性和提供商支持。
24 0
|
10天前
|
存储 Java
Java基础教程(7)-Java中的面向对象和类
【4月更文挑战第7天】Java是面向对象编程(OOP)语言,强调将事务抽象成对象。面向对象与面向过程的区别在于,前者通过对象间的交互解决问题,后者按步骤顺序执行。类是对象的模板,对象是类的实例。创建类使用`class`关键字,对象通过`new`运算符动态分配内存。方法包括构造函数和一般方法,构造函数用于对象初始化,一般方法处理逻辑。方法可以有0个或多个参数,可变参数用`类型...`定义。`this`关键字用于访问当前对象的属性。