在Java中正确使用Optional

Optional类是在Java 8中引入的,用于解决NullPointerException的问题。

java.util.Optional类是一个泛型类型的类,只包含一个类型为T的值。其目的是提供对可能为null的类型T的引用对象的更安全的替代方案。但是,只有在正确使用的情况下,Optional对象才是安全的。

创建Optional对象的方式:

Empty Optional

使用Optional.empty(),我们可以创建一个不包含任何类型的空的optional对象。

java 复制代码
//returning a empty optional of type string
public static Optional<String> emptyOptional(){
       return Optional.empty();
}

//or
Optional<String> str = Optional.empty();

Nullable Optional

使用Optional.ofNullable()方法,我们可以创建可空的Optional对象。这些对象可以是null,也可以包含值。

java 复制代码
public static Optional<Wallet> getWallet(){
        return Optional.ofNullable(null);
}

Non-Nullable Optional

使用该Optional.of()方法我们可以创建不可为 null 的可选对象。

java 复制代码
public static Optional<Wallet> getWallet(){
        return Optional.of(new Wallet(100));
}

现在让我们看一下Optional类中的不同方法,我们可以利用这些方法来编写促进空安全的清晰代码。

在Optional类中的 get() 方法用于获取值,如果存在的话,否则抛出NoSuchElementException异常。

例如,假设我们有一个具有私有字段money的Wallet对象。要获取money的值,我们可以按如下方式操作:

java 复制代码
//normal way to get money 
int savings = wallet.getMoney();

//when wallet object is wrapped in a optional 
int savings = optionalWallet.get().getMoney();

如果wallet对象为null,第二种方式比第一种方式更安全,因为它会抛出NoSuchElementException而不是NullPointerException。

我们可以通过使用isPresent()方法来改进第二种方式,该方法返回一个布尔值,指示值是否存在。

java 复制代码
List<Integer> savings = new ArrayList();
if(optionalWallet.isPresent()){
    savings.add(optionalWallet.get().getMoney());
}

但与此同时,这种方式并没有比检查非空更为简洁。

java 复制代码
List<Integer> savings = new ArrayList();
if(wallet != null){
  savings .add(wallet.getMoney());
} 

为了使代码更简洁清晰,我们可以使用ifPresent()方法,该方法接受一个Consumer或一个Runnable,或者两者都接受。使用ifPresent(),我们可以消耗一个正确的值或生成一个替代值。让我们看一下具体的用法。

java 复制代码
List<Integer> savings = new ArrayList();
optionalWallet.ifPresent(wallet -> savings.add(wallet.getMoney()));

在上面的示例中,只有当wallet不为null时,即存在时,才将money添加到savings中。

如果我们将wallet本身添加到列表中。

java 复制代码
//using lambda
List<Wallet> wallets  = new ArrayList<>();
optionalWallet.ifPresent(wallet -> wallets.add(wallet));

//you can also use method reference
List<Wallet> wallets  = new ArrayList<>();
optionalWallet.ifPresent(wallets::add);

正如你所看到的,这比一开始的示例要好得多。

在某些情况下,当optional为空时,你可能希望有一个默认值。使用orElse()方法,我们可以在optional为null时生成一个替代值。让我们看一个例子。

java 复制代码
List<Wallet> wallets  = new ArrayList<>();
Wallet wallet = optionalWallet.orElse(new Wallet(0));
wallets.add(wallet);

在上面的例子中,如果optionalWallet包含一个值,它将被赋给wallet变量;如果没有值,则分配一个值为0的默认wallet。orElse()方法可以与任何其他类型一起使用,生成默认值。

你还可以在orElseGet()方法内调用一块代码来计算一个默认值。

java 复制代码
//calculating a default value 
Wallet wallet = optionalWallet.orElseGet(() -> {
            int randomAmount = (int) (Math.random() * 500); // Generating a random amount between 0 and 500
            return new Wallet(randomAmount);
});

在使用Spring Boot应用程序和数据库时,当我们执行选择查询以获取用户时,一种良好的实践是将用户对象封装在Optional中,然后我们可以这样做:

java 复制代码
//Getting the user from database
Optional<User> findUserById(String id);

//Calling the find user method 
User user = findUserById(id)
                    .orElseThrow(UserNotFoundException::new);

在上面的例子中,你可以看到,我们不需要进行任何检查来确定用户是否存在。如果数据库中存在用户,我们将获取该用户;如果不存在,我们将在那里优雅地抛出一个异常。

相关推荐
Miqiuha6 分钟前
lock_guard和unique_lock学习总结
java·数据库·学习
一 乐1 小时前
学籍管理平台|在线学籍管理平台系统|基于Springboot+VUE的在线学籍管理平台系统设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·学习
不知所云,1 小时前
qt cmake自定义资源目录,手动加载资源(图片, qss文件)
开发语言·qt
数云界1 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
安冬的码畜日常2 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine
阑梦清川2 小时前
Java继承、final/protected说明、super/this辨析
java·开发语言
PythonFun2 小时前
Python批量下载PPT模块并实现自动解压
开发语言·python·powerpoint
Death2002 小时前
Qt 6 相比 Qt 5 的主要提升与更新
开发语言·c++·qt·交互·数据可视化
机器视觉知识推荐、就业指导2 小时前
使用Qt实现实时数据动态绘制的折线图示例
开发语言·qt
快乐就好ya3 小时前
Java多线程
java·开发语言