Java Optional 怎么用
在日常写代码时,你肯定遇到过这种情况:调用一个方法后,返回了空值(比如想从用户信息里拿住址,结果用户没填地址),直接写代码用这个值,程序就会弹出“空指针异常”直接崩溃。很多人习惯加个if判断,比如“如果这个值不是空,就做XX”,但写多了就会发现,代码里全是“if (对象 != null)”,像裹了层厚厚的“空值铠甲”,又乱又容易漏判。
要解决这个问题,Java 8 推出了Optional类,它就像一个“空值收纳盒”——把可能为空的对象装进去,要么盒子里有东西(非空),要么盒子是空的,你不用再猜“这个值是不是空”,只要按照盒子的状态来处理就行。接下来咱们用几个生活化的例子,把它的用法拆得明明白白。

第一步:把值放进Optional盒子里
想把普通值变成Optional,有三种常用方法,对应“盒子里可能有东西、确定是空、或者自动判断”三种情况:
- 如果你确定这个值一定不是空,比如固定的“系统默认用户ID=1001”,就用
Optional.of(值),如果偷偷传了null,程序直接报错,避免你糊里糊涂用了错的空值; - 如果你确定这个值可能是空,比如从用户信息里拿的“自定义昵称”,就用
Optional.ofNullable(值),它就像个弹性盒子,有东西就装,空的也能放,不会报错; - 如果你要表示“完全空的盒子”,比如查询后没找到对应用户,就用
Optional.empty(),相当于明确告诉你“这次啥都没拿到”。
举个例子:你从数据库查用户,拿到的user可能是空,就可以写Optional<User> userOpt = Optional.ofNullable(user);,这就把“可能为空的用户”包装成了带状态的盒子。
第二步:打开盒子,安全取里面的东西
拿到Optional盒子后,最核心的用法是“安全取值”,不用再写if判断。比如你想拿用户的手机号,有两种常用方式:
- 如果你确定盒子里一定有东西,比如已经确认这个用户存在,就用
get(),直接拿值就行,适合已经做过非空校验的场景; - 如果你不确定,就用
orElse(默认值),相当于“盒子空了就拿备用的”。比如String phone = userOpt.map(User::getPhone).orElse("暂无手机号");——意思是先从盒子里的用户拿手机号,空的话就返回“暂无手机号”,比写if (user != null && user.getPhone() != null)简洁多了。
还有个更灵活的方法orElseGet(方法),如果空值时需要计算默认值(比如调用另一个接口拿备用手机号),用它比orElse高效,因为只有真的空时才会执行后面的逻辑,适合备用值需要计算的场景。
第三步:盒子空了时,做特殊处理
如果Optional盒子是空的,你可能不想只拿默认值,而是要执行一段逻辑,比如给用户发“请完善手机号”的提醒,这时候用ifPresentOrElse()就很方便:userOpt.ifPresentOrElse(u -> sendReminder(u.getId()), () -> createNewUser());——意思是“盒子有用户就发提醒,盒子空了就新建用户”,把分支逻辑写得清清楚楚,不用再嵌套if。
如果遇到更复杂的情况,比如盒子空了要抛出自定义异常,还能用orElseThrow(),比如User foundUser = userOpt.orElseThrow(() -> new RuntimeException("找不到对应的用户"));,既安全又能明确错误原因。
小技巧:链式操作减少嵌套
Optional最棒的一点是支持链式操作,不用写多层if嵌套。比如你要做“查用户→拿手机号→判断手机号是否有效→发送短信”,以前的写法是:
`java
if (user != null) {
String phone = user.getPhone();
if (phone != null && phone.startsWith("1")) {
sendSms(phone);
}
}
`
用Optional链式写就是:
`java
Optional.ofNullable(user)
.map(User::getPhone)
.filter(p -> p.startsWith("1"))
.ifPresent(this::sendSms);
`
map()相当于“把盒子里的东西转成另一种内容”,filter()相当于“给盒子里的东西加个条件,不符合就变成空盒子”,整个流程一眼就能看懂,没有冗余的判断。
最后要提醒的是,Optional不是万能的,不要把它当成“所有类都用Optional封装”,比如方法参数、类的成员变量,还是用普通的null判断更合适,Optional只适合用来做“方法返回值”,帮你减少空指针异常,让代码更清爽。