两段Java代码的行为一致性确认及差异咨询
两段Optional代码的行为差异分析
嘿,咱们来好好捋捋这两段代码的区别——其实你之前以为它们在无数据时都会抛NoSuchElementException的认知是不对的,第一段代码根本不会在查询后立即抛出异常,具体拆解如下:
首先得明确一个前提:Spring Data JPA的freePostsRepository.findById(id)方法本身就返回Optional<FreePosts>类型的结果——当数据库里找不到对应id的记录时,它返回的是Optional.empty(),而不是null。
先看第二段代码(正确且符合预期的写法)
FreePosts byId = freePostsRepository.findById(id) .orElseThrow(NoSuchElementException::new);
- 这段逻辑非常直接:直接对
findById返回的Optional<FreePosts>调用orElseThrow方法- 如果查询到数据,
Optional里包含有效对象,orElseThrow会直接返回这个对象,赋值给FreePosts类型的变量byId; - 如果没查到数据,
Optional是空的,orElseThrow会立刻抛出NoSuchElementException,完全符合你预期的行为。
- 如果查询到数据,
再看第一段代码(冗余且不符合预期的写法)
Optional<FreePosts> byId = Optional.ofNullable(freePostsRepository.findById(id)) .orElseThrow(NoSuchElementException::new);
- 这里多做了一步画蛇添足的操作:用
Optional.ofNullable()把findById返回的Optional<FreePosts>又包装了一层,变成了Optional<Optional<FreePosts>>- 因为
findById永远不会返回null(只会返回有值的Optional或Optional.empty()),所以外层的Optional.ofNullable()得到的永远是一个非空的Optional——里面要么装着有数据的Optional<FreePosts>,要么装着空的Optional<FreePosts>; - 这时候调用
orElseThrow完全不会触发异常——因为外层的Optional从来都不是空的,它只会把里面的那个Optional<FreePosts>返回给变量byId; - 也就是说,当无数据时,这段代码只会得到一个
Optional.empty()的变量,只有当你后续调用byId.get()时才会抛出NoSuchElementException,和你原本以为的“查询时抛异常”完全不是一回事。
- 因为
核心差异总结
- 类型差异:第二段代码直接拿到
FreePosts实体对象,第一段拿到的是Optional<FreePosts>包装类; - 异常触发时机:第二段在查无数据时立即抛出异常,第一段只有在后续调用
get()方法时才会抛异常; - 冗余性:第一段的
Optional.ofNullable()完全多余,因为findById的返回值本身就是Optional类型,不可能为null。
内容的提问来源于stack exchange,提问作者남세원
相关产品推荐
相关产品推荐

