Java8 Optional使用详解

文章目录

  • [Optional 简介](#Optional 简介)
  • [1 使用Optional创建返回值](#1 使用Optional创建返回值)
    • [1.1 使用of创建非空对象](#1.1 使用of创建非空对象)
    • [1.2 使用ofNullable创建可以为空的对象](#1.2 使用ofNullable创建可以为空的对象)
  • [2 对Optional的处理](#2 对Optional的处理)
    • [2.1 使用 非空表达式 处理对象 ifPresent](#2.1 使用 非空表达式 处理对象 ifPresent)
    • [2.2 设置默认值(空值下的处理)](#2.2 设置默认值(空值下的处理))
    • [2.3 过滤值](#2.3 过滤值)
    • [2.4 转换值](#2.4 转换值)
  • [3 综合应用](#3 综合应用)
  • 参考:

Optional 简介

使用Optional用来表示一个引用对象存在或者不存在

Optional类主要用来处理返回值为null的情况,避免出现对返回对象操作发生NullPointerException的情况,使得代码更加健壮

Optional是容器对象,可能包含或者不包含非NULL值

常用API

  • ofNullable创建Optional对象
  • ifPresent对非null对象继续处理
  • orElseGet对null设置默认值
  • filter过滤结果
  • map映射新的Optional对象

正确使用Optional

  • 避免使用Optional.isPresent来检查实例是否存在,然后再操作,这样与if (obj != null)的使用方式没有区别,可以使用Optional.ifPresent(u -> System.out.println(u.getName())))
  • 避免使用Optional.get来获取对象,可能会出现NPE(NullPointerException)的问题,使用设置默认值的方式获取Optional对象,userOpt.orElseGet(() -> new User(-1, "Empty"))
  • 避免使用Optional作为类或者实例属性
  • 避免使用Optional作为方法的参数

1 使用Optional创建返回值

1.1 使用of创建非空对象

java 复制代码
public String findUserById(int id) {  
    if (id == 1) {  
        return "Alice";  
    } else {  
        return null;  
    }
}

使用Option处理

java 复制代码
import java.util.Optional;  
  
public Optional<String> findUserById(int id) {  
    if (id == 1) {  
        return Optional.of("Alice");  
    } else {  
        return Optional.empty();  
    }  
}

传入Optional.of的方法的参数必须时非空的,否则抛出NPE,使用ofNullable来创建非空值

1.2 使用ofNullable创建可以为空的对象

java 复制代码
User user = null;
Optional<User> userOpt = Optional.ofNullable(user);

2 对Optional的处理

2.1 使用 非空表达式 处理对象 ifPresent

如果对象存在,则对其进行处理,否则不处理

java 复制代码
userOpt.ifPresent(u -> System.out.println(u.getName()));

2.2 设置默认值(空值下的处理)

创建Optional对象的时候,设置默认值

1 基本用法

如果对象不为null,则返回该对象;

java 复制代码
User user = null;
User myUser = Optional.ofNullable(user).orElse(new User(-1, "Empty"))
2 表达式处理的区别

orElse的参数类型不同,如果对象为null,则执行表达式

java 复制代码
User user = null;
User myUser = Optional.ofNullable(user).orElseGet(() -> new User(-1, "Empty"))
两种设置默认值方法的不同

当Optional中的对象为null的时候,orElseGet方法并不会执行

java 复制代码
public static void getValue() { System.out.println("getValue!"); }

User user = null;
System.out.println("orElse")
User testUser1 = Optional.ofNullable(user).orElse(getValue());
System.our.println("orElseGet")
User testUser2 = Optional.ofNullable(user).orElseGet(Main::getValue)

注意: 类名::方法名是Java8新语法,表明该方法不一定会被调用

输出

shell 复制代码
orElse
getValue!
orElseGet

使用orElseGet的性能会更佳!

2.3 过滤值

对Optional中的对象进行按照条件进行筛选

需求:筛选id大于10的user

java 复制代码
User user = new User(100, "zhangsan");
Optional<User> userOpt = Optional.ofNullable(user);
userOpt.filter(u -> u.id > 10).ifPresent(System.out.println(u.getName));

存在多个条件:id大于10并小于100

java 复制代码
Predicate<User> userIdGt10 = u -> u.id > 10;
Predicate<User> userIdLt100 = u -> u.id < 100;

User use = new User(30, "lisi");
Optional<User> userOpt = Optional.ofNullable(user);
userOpt.filter(u -> userIdGt10.and(userIdLt100)).ifPresent(System.out.println(u.getName()));

使用optional进行条件过滤,使用一行代码就可以解决;如果使用if-else代码比较冗长

2.4 转换值

将一个Optional对象转换为另一个Optional对象

需求:取出user中的Name

java 复制代码
User user = new User(10, "zhangsan");
Optional<User> userOpt = Optional.ofNullable(user);
Optional<String> name = userOpt.map(User::getName);
name.orElseGet(() -> "empty").ifPresent(str -> System.out.println(str));

3 综合应用

对user对象设置默认值,并筛选其中长度大于10小于100的user的小写名字

java 复制代码
Predicate<String> lenGt10 = name -> name.length() > 10;
Predicate<String> lenLt100 = name -> name.length() < 100;

User user = new User(10, "zhangsan");
Optional<User> userOpt = Optional.ofNullable(user);
userOpt.orElseGet(() -> new User(-1, "")).map(User::getName).map(String::toLowerCase).fileter(lenGt10.and(lenLt100)).ifPresent(name -> System.out.println(name));

参考:

Java8 Optional最佳指南,优雅解决空指针 https://javabetter.cn/java8/optional.html

Java8 Optional使用总结 https://www.cnblogs.com/kingsonfu/p/11009574.html

相关推荐
丹牛Daniel5 分钟前
Java解决HV000183: Unable to initialize ‘javax.el.ExpressionFactory‘
java·开发语言·spring boot·tomcat·intellij-idea·个人开发
消失的旧时光-194323 分钟前
智能指针(三):实现篇 —— shared_ptr 的内部设计与引用计数机制
java·c++·c·shared_ptr
芒克芒克27 分钟前
深入浅出CopyOnWriteArrayList
java
wuqingshun31415936 分钟前
说一下java的反射机制
java·开发语言·jvm
A懿轩A40 分钟前
【Java 基础编程】Java 异常处理保姆级教程:try-catch-finally、throw/throws、自定义异常
java·开发语言·python
极客先躯1 小时前
高级java每日一道面试题-2025年7月14日-基础篇[LangChain4j]-如何集成开源模型(如 Llama、Mistral)?需要什么基础设施?
java·langchain·存储·计算资源·模型服务框架·网络 / 协议·java 依赖
黎雁·泠崖1 小时前
Java 包装类:基本类型与引用类型的桥梁详解
java·开发语言
盖头盖2 小时前
【Java反序列化基础】
java
极客先躯2 小时前
高级java每日一道面试题-2025年7月15日-基础篇[LangChain4j]-如何集成国产大模型(如通义千问、文心一言、智谱 AI)?
java·人工智能·langchain·文心一言·异常处理·密钥管理·参数调优
追随者永远是胜利者3 小时前
(LeetCode-Hot100)226. 翻转二叉树
java·算法·leetcode·职场和发展·go