Java中的Optional类

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

java中尝试访问空引用的属性调用空引用的方法是会报空指针NullPointerException异常。实际项目中会处理大量为空的值,代码会有很多的条件判断,难以阅读与维护。

        if(user!=null){
            System.out.println(user.getFullName());
        }else {
            User defaultUser = new User("Stark", "Tony Stark");
            System.out.println(defaultUser.getFullName());
        }

本笔记为总结视频内容中的Java中的Optional类的使用方法。
视频链接:https://www.bilibili.com/video/BV1dc411X7nW

一、Optional是什么?

Optional类引入了一种显式的方式来处理可能为空的对象,强制程序员在可能为空的情况下进行显式的处理,以避免空指针异常。
Optional类似容器,可以包含各种类型的值,也可以为null。Optional类提供了一系列方法来方便地操作内部的值。常用的方法有get、orElse、orElseGet、orElseThrow等。
Optional的设计也考虑了函数式编程的原则,可以与Lambda表达式和StreamAPI等特性结合使用,可以进行链式调用替代命令式编程的方式通过编写if条件语句检查null值。

二、Optional对象的方法

首先我们需要创建两个类,User类与UserRepository类。
User类

import java.util.Optional;

public class User {
    String name;
    String fullName;

    public User(String name, String fullName) {
        this.name = name;
        this.fullName = fullName;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getFullName() {
        return fullName;
    }

    public void setFullName(String fullName) {
        this.fullName = fullName;
    }
}

UserRepository类

import java.util.Optional;

public class UserRepository {
    public User findUserByName(String name){
        if(name.equals("Peter")){
            return new User("Peter","Peter Parker");
        }
        else {
            return null;
        }
    }
}

1.isPresent、isEmpty方法

isPresent方法用于检查optional内是否存在值,返回为布尔值,存在为true,不存在为false。
isEmpty方法用于检查optional内是否为空,返回为布尔值,为空为true,不为空为false。

		//创建值为null的Optional对象
		Optional<Object> optionalBox = Optional.empty();
		System.out.println(optionalBox.isPresent());
		System.out.println(optionalBox.isEmpty());

返回值为false与true。

2.empty、of、ofNullable方法

若创建的对象为null,则可以采用empty()方法。

		Optional<Object> optionalBox = Optional.empty();

创建不为null的对象需要调用of方法,此时若value为null,则抛出NullPointerException异常。

        String value = "Peter";
        Optional<String> optionalBox = Optional.of(value);

若想要创建可能为null的对象,可以使用ofNullable( )方法。

        String value = "Peter";
        Optional<String> optionalBox = Optional.ofNullable(value);

3.get、orElse、orElseGet与orElseThrow方法

取值可以使用get()方法,若取值对象为null,会报java.util.NoSuchElementException异常(并非java.lang.NullPointerException异常)。

        String value2 = optionalBox.get();
        System.out.println(value2);

我们这里修改UserRepository类中的findUserByName方法,使其返回值为Optional对象。

    public Optional<User> findUserByName(String name){
        if(name.equals("Peter")){
            return Optional.of(new User("Peter","Peter Parker"));
        }
        else {
            return Optional.empty();
        }
    }

orElse是Optional类中的一个重要方法,它用于获取值或在值为空的情况下提供一个默认值。

        UserRepository userRepository = new UserRepository();
        Optional<User> optionalUser = userRepository.findUserByName("Peter2");
        User user = optionalUser.orElse(new User("Stark","Tony Stark"));
        System.out.println(user.getFullName());

orElse方法即使读到的数据不为null,仍会创建一个新User对象。因此最好使用只有读到的数据为null的时候才会新建对象的orElseGet方法。
orElseGet方法的参数为Supplier的函数式接口,需要使用Lambda表达式实现。

        optionalUser.orElseGet(()->new User("Stark","Tony Stark"));
        System.out.println(user.getFullName());

orElseThrow方法用于在 Optional 对象中的值为空时抛出一个指定的异常。
orElseThrow方法通过Supplier的函数式接口,可以生成自定义异常,默认抛出异常为java.util.NoSuchElementException。

        UserRepository userRepository = new UserRepository();
        Optional<User> optionalUser = userRepository.findUserByName("Peter2");
        optionalUser.orElseThrow(()->new RuntimeException("User not found"));

4.ifPresent、ifPresentOrElse、filter方法

ifPresent方法参数中若对象不为null,则会执行Labmda中的方法;
若参数对象为null,则不会执行Labmda中的方法,也不会报错。

        UserRepository userRepository = new UserRepository();
        Optional<User> optionalUser = userRepository.findUserByName("Peter2");
        optionalUser.ifPresent(user -> System.out.println(user.getFullName()));

当我们希望值为空时进行其他操作,需要使用ifPresentOrElse方法。

        optionalUser.ifPresentOrElse(user -> System.out.println(user.getFullName()),
                ()->System.out.println("User not found"));

若满足filter方法中的条件,则会返回包含值的Optional对象,如果不满足,则返回空的Optional对象

        Optional<User> optionalUser2 = optionalUser.filter(user -> user.getFullName().equals("Peter Parker"));
        System.out.println(optionalUser2.isPresent());

5.Map与flatMap方法

进行两个方法前需要将User类中的 getFullName方法返回值修改为Optional。

    public Optional<String> getFullName(){
        return Optional.ofNullable(fullName);
    }

map方法:对Optional中的值进行转换(若值为空,则map方法什么也不会做,直接返回空的Optional对象)。
这个变换基于提供该map的函数,并且这个变换是可选的,如果optional的值为空则不会做任何改变,并且map方法不会改变原始的Optional对象,而返回新的Optional对象,因此可以链式调用进行多个转换操作。

        UserRepository userRepository = new UserRepository();
        Optional<User> optionalUser = userRepository.findUserByName("Peter");
        Optional<String> optionalFullName = optionalUser.map(User::getFullName);
        System.out.println(optionalFullName.get());

flatmap方法用于扁平化嵌套的Optional结构,以避免引入不必要的嵌套层级,具体为flatmap的转换函数返回的必须是另一个Optional对象,意味着flatMap方法可以用于嵌套的Optional情况,可以将两个为嵌套关系的Optional对象转换为一个。如果原始的Optional对象为空,或转换函数返回的Optional对象为空,那么最终得到的也是为空的Optional对象。

        UserRepository userRepository = new UserRepository();
        Optional<User> optionalUser = userRepository.findUserByName("Peter");
        Optional<String> optional = optionalUser.flatMap(User::getFullName);

若只需要对Optional对象中的值进行转换,而不需要嵌套的Optional,那么使用map方法更合适
如果要进行一些操作返回另外一个Optional对象,flatmap方法更合适。

6.Stream方法

Optional的stream方法,可以将Optional对象转换为Stream对象,对其中的值进行流操作,如果Optional对象包含值,则将这个值封装到一个Stream流中,如果Optional对象为空,则创造一个为空的Stream流

        UserRepository userRepository = new UserRepository();
        Optional<User> optionalUser = userRepository.findUserByName("Peter");
        Stream<String> a =optionalUser.map(User::getName).stream();
        a.forEach(System.out::println);

三、不适合使用Optional对象的情况

不应该用于类的字段,会增加内存消耗,并使序列化变得复杂;
不应该用于方法参数,使方法的理解和使用变得复杂;
不应用于构造器参数,迫使调用者创建Optional实例,应该通过构造器重载解决;
不应该用于集合的参数,集合已经很好的处理空集合的情况,没必要使用Optional包装集合;
不建议使用get方法,若为null会报错。

总结

以上就是今天要讲的内容,本文简单介绍了Optional对象的使用以及不适合使用Optional对象的情况。

  • 9
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
OptionalJava 8引入的一个用于解决空指针异常问题的容器。它可以包含一个非空的值,也可以表示为空。Optional的设计目的是为了避免在代码频繁使用null值,从而提高代码的可读性和健壮性。 使用Optional可以有效地处理可能为空的值,避免出现NullPointerException。它提供了一系列方法来判断Optional对象是否包含值,如果有值则可以通过get()方法获取该值,或者使用orElse()方法指定一个默认值。 下面是一个示例代码,演示了如何使用Optional: ```java Optional<String> optionalValue = Optional.of("Hello World"); if (optionalValue.isPresent()) { String value = optionalValue.get(); System.out.println(value); } else { System.out.println("Value is absent"); } String defaultValue = optionalValue.orElse("Default Value"); System.out.println(defaultValue); ``` 在上面的代码,我们首先使用`Optional.of()`方法创建了一个包含非空值的Optional对象。然后通过`isPresent()`方法判断Optional对象是否包含值,如果有值则通过`get()`方法获取该值并输出。如果Optional对象为空,则输出"Value is absent"。 接下来使用`orElse()`方法指定了一个默认值,并输出该默认值。如果Optional对象包含值,则输出原始值;如果Optional对象为空,则输出指定的默认值。 使用Optional可以有效地避免空指针异常,并提高代码的可读性和健壮性。它在编写Java代码时是一个非常有用的工具。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值