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

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

相关推荐
m0_5719575843 分钟前
Java | Leetcode Java题解之第543题二叉树的直径
java·leetcode·题解
一点媛艺2 小时前
Kotlin函数由易到难
开发语言·python·kotlin
姑苏风2 小时前
《Kotlin实战》-附录
android·开发语言·kotlin
奋斗的小花生3 小时前
c++ 多态性
开发语言·c++
魔道不误砍柴功3 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_2343 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
闲晨3 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
老猿讲编程3 小时前
一个例子来说明Ada语言的实时性支持
开发语言·ada
Chrikk4 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*4 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go