java中Optional类的使用和注意采坑

一  Optional类的使用

1.1. 闭坑案例

1.1.1 代码

public class Bianli {
    public static void main(String[] args) {
        ChatInfo chatInfo = new ChatInfo();
        chatInfo.setId(1);
        List<Message> messageList = new ArrayList<>();
        Message  message = new Message();
       message.setRole("user4");
        message.setContent("nihao");
        messageList.add(message);
        Message  message2 = new Message();
       message2.setRole("user3");
        message2.setContent("nihao222");
       messageList.add(message2);
        chatInfo.setMessageList(messageList);
        //
       Optional<Message> op = chatInfo.getMessageList().stream().filter(m -> m.getRole().equals("user")).findFirst();
     //   Optional<Message> op = chatInfo.getMessageList().stream().filter(m -> "user".equals(m.getRole())).findFirst();
           System.out.println("op:"+op);
          //  System.out.println("op:"+op.get());
////        System.out.println("op:"+op.isPresent());
         if(!op.isPresent()||op.get()==null){
             System.out.println("null ....");
         }
    }
}

1.1.2 作用

chatInfo.getMessageList().stream().filter(m -> m.getRole().equals("user")).findFirst();

作用:返回流中第一个符合条件的元素(按照流的顺序),并用 Optional 包装结果。

findFirst() 应该总是与 filter() 配合使用,且由于返回 Optional,后续操作必须考虑空值处理(如 isPresent() 检查或使用 orElse() 等方法)。

1.1.3 风险

风险说明:

.filter(m -> "user".equals(m.getRole()))  // 即使 m.getRole() 为 null 也安全

op.get() 的安全隐患:直接调用 get() 是危险操作:

当 Optional 为空时(op.isPresent() == false),调用 get() 会抛出:java.util.NoSuchElementException: No value present

Optional<Integer> empty = Optional.empty();

empty.get(); // 抛出 NoSuchElementException(危险!)

使用安全模式:必须先检查isPresent()

如:

Optional<Integer> empty = Optional.empty();

If(empty.isPresent()){

empty.get();

}

<think>在Java中,`Optional`是一个容器对象,用于处理可能为`null`的值。它提供了一种优雅的方式来避免显式的`null`检查,防止`NullPointerException`。`Optional`Java8中引入,位于`java.util`包中。###主要功能:1.**避免Null检查**:通过封装可能为`null`的值,`Optional`鼓励程序员显式处理值缺失的情况,而不是通过`if(obj!=null)`这样的检查。2.**链式方法调用**:`Optional`提供了一系列方法(如`map`、`flatMap`、`filter`)来支持链式调用,使代码更简洁。3.**明确表达意图**:使用`Optional`可以明确表示某个返回值可能为空,调用者必须处理这种情况。###常用方法:1.**创建Optional对象**:-`Optional.empty()`:创建一个空的`Optional`实例。-`Optional.of(Tvalue)`:创建一个非空的`Optional`实例,如果`value`为`null`,则抛出`NullPointerException`。-`Optional.ofNullable(Tvalue)`:创建一个可能为空的`Optional`实例,如果`value`为`null`,则返回一个空的`Optional`。2.**检查值是否存在**:-`isPresent()`:如果值存在则返回`true`,否则返回`false`。-`isEmpty()`(Java11引入):如果值不存在(即为空)则返回`true`,否则返回`false`。3.**获取值**:-`get()`:如果值存在则返回该值,否则抛出`NoSuchElementException`。通常建议在调用`get()`之前先检查`isPresent()`。-`orElse(Tother)`:如果值存在则返回该值,否则返回指定的默认值`other`。-`orElseGet(Supplier<?extendsT>supplier)`:如果值存在则返回该值,否则使用提供的`Supplier`函数式接口生成一个默认值。-`orElseThrow(Supplier<?extendsX>exceptionSupplier)`:如果值存在则返回该值,否则抛出由提供的`Supplier`创建的异常。4.**链式操作**:-`map(Function<?superT,?extendsU>mapper)`:如果值存在,则对其应用提供的映射函数,并返回一个包含映射结果的`Optional`(如果映射结果为`null`,则返回空的`Optional`);否则返回空的`Optional`。-`flatMap(Function<?superT,Optional<U>>mapper)`:似于`map`,但要求映射函数返回一个`Optional`对象,然后将其扁平化为一个`Optional`。-`filter(Predicate<?superT>predicate)`:如果值存在且满足给定的谓词条件,则返回包含该值的`Optional`;否则返回空的`Optional`。###示例代码:下面是一个使用`Optional`的示例,展示了如何避免`NullPointerException`。```javaimportjava.util.Optional;publicclassOptionalExample{publicstaticvoidmain(String[]args){//创建一个可能为null的字符串Stringname="Alice";//使用Optional包装Optional<String>opt=Optional.ofNullable(name);//检查是否有值if(opt.isPresent()){System.out.println("Name:"+opt.get());}//使用orElse提供默认值StringnullName=null;Stringresult=Optional.ofNullable(nullName).orElse("Unknown");System.out.println("Result:"+result);//输出:Unknown//使用orElseGet通过Supplier提供默认值Stringresult2=Optional.ofNullable(nullName).orElseGet(()->"GeneratedName");System.out.println("Result2:"+result2);//输出:GeneratedName//使用map进行转换Optional<String>upperCaseName=opt.map(String::toUpperCase);System.out.println(upperCaseName.orElse("Nonamefound"));//输出:ALICE//使用filterOptional<String>filtered=opt.filter(n->n.length()>4);System.out.println(filtered.orElse("Nameistooshort"));//输出:Alice(因为长度5>4)//使用flatMapOptional<String>flatMapped=opt.flatMap(n->Optional.of(n+"ishere"));System.out.println(flatMapped.orElse("Noname"));//输出:Aliceishere}}```###解释:-创建`Optional`对象时,使用`ofNullable`可以安全地处理可能为`null`的值。-使用`orElse``orElseGet`提供默认值,区别在于`orElseGet`接受一个`Supplier`,只有在需要时才计算默认值,避免不必要的计算。-`map`方法用于转换值,如果值存在则应用函数,否则不进行操作。-`filter`方法用于过滤,如果值满足条件则保留,否则返回空`Optional`。-`flatMap`用于当映射函数本身返回一个`Optional`时,避免嵌套的`Optional`(如`Optional<Optional<String>>`)。###注意事项:-不要将`Optional`作为的字段、方法参数或集合的元素,因为它不是可序列化的,而且设计初衷是作为返回型。-避免在`Optional`上使用`get()`方法而不检查是否存在值,这可能导致`NoSuchElementException`。§§相关问题§§:1.在Java中,`Optional`的主要设计目的是什么?2.`Optional.of()``Optional.ofNullable()`有什么区别?3.请解释`orElse()``orElseGet()`方法的区别,并举例说明。4.如何正确使用`Optional`来避免`NullPointerException`?</think>### JavaOptional的功能常用方法 `Optional`是Java 8引入的容器,主要解决`NullPointerException`问题。它封装可能为`null`的值,强制开发者显式处理空值情况,提高代码可读性安全性。 #### 核心功能: 1. **显式处理空值**:强制开发者考虑值缺失的情况 2. **链式调用**:支持函数式编程风格的链式操作 3. **减少NPE**:避免深层嵌套的null检查 #### 常用方法及代码示例: ```java import java.util.Optional; public class OptionalDemo { public static void main(String[] args) { // 1. 创建Optional Optional<String> emptyOpt = Optional.empty(); // 空容器 Optional<String> nonNullOpt = Optional.of("Hello"); // 非null值(null会抛NPE) Optional<String> nullableOpt = Optional.ofNullable(null); // 允许null // 2. 值存在性检查 String value = "Java"; Optional<String> opt = Optional.ofNullable(value); System.out.println("Value present: " + opt.isPresent()); // true System.out.println("Value absent: " + emptyOpt.isEmpty()); // true (Java 11+) // 3. 安全获取值 // orElse: 有值返回值,无值返回默认值 System.out.println(emptyOpt.orElse("Default")); // Default // orElseGet: 延迟计算的默认值 System.out.println(emptyOpt.orElseGet(() -> "Computed Default")); // orElseThrow: 无值时抛出异常 try { emptyOpt.orElseThrow(() -> new RuntimeException("Value missing")); } catch (Exception e) { System.out.println(e.getMessage()); // Value missing } // 4. 链式操作 // map: 值转换 Optional<String> upperOpt = opt.map(String::toUpperCase); System.out.println(upperOpt.get()); // JAVA // flatMap: 解包嵌套Optional Optional<Optional<String>> nested = Optional.of(Optional.of("Nested")); Optional<String> flat = nested.flatMap(o -> o.map(String::toLowerCase)); System.out.println(flat.get()); // nested // filter: 条件过滤 Optional<String> filtered = opt.filter(s -> s.length() > 3); System.out.println(filtered.get()); // Java } } ``` #### 关键方法说明: 1. **创建方法**: - `Optional.empty()`:创建空Optional - `Optional.of(T value)`:创建非null值的Optional(参数不能为null) - `Optional.ofNullable(T value)`:创建可能为null的Optional 2. **值获取**: - `get()`:直接获取值(空容器会抛`NoSuchElementException`) - `orElse(T other)`:有值返回值,无值返回指定默认值 - `orElseGet(Supplier<T> supplier)`:无值时通过Supplier生成默认值 - `orElseThrow(Supplier<X> exceptionSupplier)`:无值时抛出指定异常 3. **链式操作**: - `map(Function<T, U> mapper)`:值转换(自动解包) - `flatMap(Function<T, Optional<U>> mapper)`:处理嵌套Optional - `filter(Predicate<T> predicate)`:条件过滤 4. **状态检查**: - `isPresent()`:值是否存在(Java 8+) - `isEmpty()`:是否为空(Java 11+) #### 最佳实践: 1. 避免直接使用`get()`,优先使用安全获取方法 2. 不要用Optional作为方法参数(违反设计初衷) 3. 集合返回空集合而非`Optional.empty()` 4. 链式操作替代深层null检查
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值