【WPF】 Storyboard 故事板动画设计深度解析
2026/6/10 3:07:02
Optional 是 Java 8 引入的容器类,专门用于解决NullPointerException问题,让代码更加安全、优雅。
// 1. 创建包含非空值的 Optional Optional<String> nonEmpty = Optional.of("Hello"); // 2. 创建可能为空的 Optional Optional<String> nullable = Optional.ofNullable(getStringThatMightBeNull()); // 3. 创建空 Optional Optional<String> empty = Optional.empty();// ❌ 危险:如果 value 为 null 会抛出异常 Optional.of(null); // ✅ 安全:允许 null 值 Optional.ofNullable(null);Optional<String> optional = Optional.ofNullable(getData()); // 传统判空方式 if (optional.isPresent()) { String value = optional.get(); System.out.println(value); } // 函数式写法 optional.ifPresent(value -> System.out.println(value));// 如果值为空,返回默认值 String result1 = optional.orElse("默认值"); // 延迟计算的默认值(只有需要时才计算) String result2 = optional.orElseGet(() -> expensiveOperation()); // 如果为空抛出指定异常 String result3 = optional.orElseThrow(() -> new RuntimeException("值不存在"));if 嵌套改写
// 传统嵌套判空(丑陋的代码) if (user != null) { Address address = user.getAddress(); if (address != null) { String city = address.getCity(); if (city != null) { System.out.println(city.toUpperCase()); } } } // Optional 优雅写法 Optional.ofNullable(user) .map(User::getAddress) .map(Address::getCity) .map(String::toUpperCase) .ifPresent(System.out::println);Optional<User> userOpt = Optional.ofNullable(user); // 只有年龄大于18的用户才处理 userOpt.filter(u -> u.getAge() > 18) .ifPresent(u -> sendAdultNotification(u));三目运算用Optional.ofNullable-orElse替换
// 传统方式(容易产生 NPE) public String findUserName(Long id) { User user = userRepository.findById(id); // 三目运算 return user != null ? user.getName() : null; // ❌ 可能返回 null } // Optional 优化版 public Optional<String> findUserName(Long id) { // Optional.ofNullable-orElse return Optional.ofNullable(userRepository.findById(id)) .map(User::getName); // ✅ 明确表示可能为空 } // 使用示例 findUserName(123L).ifPresent(name -> System.out.println("用户名: " + name));public class Configuration { private String host; private Integer port; // 传统方式 public String getHost() { return host != null ? host : "localhost"; } // Optional 优化 public Optional<String> getHost() { return Optional.ofNullable(host); } public String getHostWithDefault() { return getHost().orElse("localhost"); } }List<String> names = users.stream() .map(User::getNickname) // 可能返回 null .filter(Objects::nonNull) // 过滤掉 null .collect(Collectors.toList()); // 更优雅的 Optional 方式 List<String> safeNames = users.stream() .map(user -> Optional.ofNullable(user.getNickname())) .filter(Optional::isPresent) .map(Optional::get) .collect(Collectors.toList()); // 或者使用 flatMap List<String> bestNames = users.stream() .map(user -> Optional.ofNullable(user.getNickname())) .flatMap(Optional::stream) // Java 9+ 特性 .collect(Collectors.toList());Optional<String> optional = getOptionalData(); // ❌ 危险:可能抛出 NoSuchElementException String value = optional.get(); // ✅ 安全:先检查再获取 if (optional.isPresent()) { String value = optional.get(); } // ✅ 更安全:使用 orElse 系列方法 String value = optional.orElse("default");// ❌ 不推荐:使 API 复杂化 public void processData(Optional<String> data) { data.ifPresent(this::doSomething); } // ✅ 推荐:使用重载方法 public void processData(String data) { doSomething(data); } public void processData() { // 处理空值情况 }// ❌ 过度使用:简单情况不需要 Optional Optional<String> name = Optional.of("张三"); // ✅ 直接使用即可 String name = "张三";| 方法 | 描述 | 使用场景 |
|---|---|---|
of() | 创建非空 Optional | 确定值不为 null |
ofNullable() | 创建可能为空的 Optional | 处理可能为 null 的值 |
empty() | 创建空 Optional | 表示明确的空值 |
isPresent() | 检查值是否存在 | 条件判断 |
ifPresent() | 值存在时执行操作 | 替代 if-not-null 检查 |
orElse() | 提供默认值 | 空值替换 |
orElseGet() | 延迟提供默认值 | 默认值计算成本高时 |
orElseThrow() | 空值时抛出异常 | 强制要求值存在 |
map() | 值转换 | 链式操作 |
flatMap() | 扁平化转换 | 避免 Optional 嵌套 |
filter() | 条件过滤 | 满足条件才处理 |
Optional 的核心价值:
使用原则:
========================================================================
集合应用:
是的,Optional 可以对集合进行判空处理,但需要根据具体场景选择合适的方式。
List<String> list = getListFromSomewhere(); // 使用 Optional 包装整个集合 Optional<List<String>> optionalList = Optional.ofNullable(list); // 判断集合是否存在且不为空 if (optionalList.isPresent() && !optionalList.get().isEmpty()) { // 处理非空集合 processList(optionalList.get()); } // 更优雅的写法 optionalList.filter(l -> !l.isEmpty()) .ifPresent(this::processList);public static <T> boolean isCollectionEmpty(Collection<T> collection) { return Optional.ofNullable(collection) .map(Collection::isEmpty) .orElse(true); // 如果集合为null,则认为空 } // 使用示例 List<String> list = null; System.out.println(isCollectionEmpty(list)); // true list = new ArrayList<>(); System.out.println(isCollectionEmpty(list)); // true list = Arrays.asList("a", "b"); System.out.println(isCollectionEmpty(list)); // falsepublic static <T> List<T> getNonNullList(List<T> list) { return Optional.ofNullable(list) .orElse(Collections.emptyList()); } // 使用示例 List<String> result = getNonNullList(possiblyNullList); result.forEach(System.out::println); // 安全,不会NPEpublic List<User> findUsersByCondition(Condition condition) { // 传统方式 List<User> users = userRepository.findByCondition(condition); return users != null ? users : Collections.emptyList(); // Optional 方式 return Optional.ofNullable(userRepository.findByCondition(condition)) .orElse(Collections.emptyList()); }// 传统方式(容易忘记判空) List<String> names = userList.stream() // 如果userList为null会NPE .map(User::getName) .collect(Collectors.toList()); // Optional 安全方式 List<String> safeNames = Optional.ofNullable(userList) .orElse(Collections.emptyList()) .stream() .map(User::getName) .collect(Collectors.toList());public class Company { private List<Department> departments; // getter/setter } public class Department { private List<Employee> employees; // getter/setter } // 传统嵌套判空 if (company != null && company.getDepartments() != null) { for (Department dept : company.getDepartments()) { if (dept.getEmployees() != null) { // 处理员工 } } } // Optional 链式判空 Optional.ofNullable(company) .map(Company::getDepartments) .orElse(Collections.emptyList()) .stream() .map(Department::getEmployees) .filter(Objects::nonNull) .flatMap(List::stream) .forEach(employee -> processEmployee(employee));// ❌ 过度复杂化 Optional.ofNullable(list) .filter(l -> !l.isEmpty()) .ifPresent(l -> l.forEach(...)); // ✅ 简单情况直接判断 if (list != null && !list.isEmpty()) { list.forEach(...); }// 对于性能敏感的场景,直接判断可能更高效 // Optional 创建对象有开销,在循环中慎用// Java 提供的便捷方法 if (CollectionUtils.isEmpty(list)) { // 很多工具库提供 // 处理空集合 } // 或者使用 Apache Commons 或 Guava if (com.google.common.collect.Iterables.isEmpty(collection)) { // 处理空集合 }// 返回集合的方法应该避免返回null public List<String> getItems() { // 而不是返回 null return Collections.emptyList(); } // 如果确实可能为null,使用Optional明确表示 public Optional<List<String>> findItems() { // 明确表示可能没有结果 }// 创建工具方法统一处理 public class CollectionUtils { public static <T> Stream<T> safeStream(Collection<T> collection) { return Optional.ofNullable(collection) .orElse(Collections.emptyList()) .stream(); } } // 使用示例 CollectionUtils.safeStream(possiblyNullList) .map(...) .filter(...) .collect(...);Optional 对集合判空的优势:
NullPointerException适用场景:
简单规则:
if (list != null && !list.isEmpty())