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

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

相关推荐
程序员-小李11 分钟前
餐厅下单助手系统(Java+MySQL)
java·开发语言·mysql
开心工作室_kaic15 分钟前
springboot496基于java手机销售网站设计和实现(论文+源码)_kaic
java·开发语言·智能手机
像少年啦飞驰点、17 分钟前
SpringBoot + HttpSession 自定义生成sessionId
java·开发语言
珊珊来吃22 分钟前
EXCEL中给某一列数据加上双引号
java·前端·excel
我曾经是个程序员29 分钟前
使用C#生成一张1G大小的空白图片
java·算法·c#
raysync88832 分钟前
替代传统FTP传输,镭速大数据传输系统实现安全高效数据流转!
开发语言·安全·php
向阳121833 分钟前
mybatis SqlSessionFactory
java·mybatis
mask哥33 分钟前
算法:LeetCode470_用Rand7()实现Rand10()_java实现
java·开发语言
Suwg20938 分钟前
《手写Mybatis渐进式源码实践》实践笔记(第七章 SQL执行器的创建和使用)
java·数据库·笔记·后端·sql·mybatis·模板方法模式
丁总学Java41 分钟前
优化 invite_codes 表的 SQL 创建语句
java·数据库·sql