目录
优雅解决方案三:使用 Objects 类的 requireNonNull 方法
⭐️引言
NullPointerException(空指针异常)是 Java 开发者经常遇到的问题,它通常由于访问或操作一个空对象引起。本文将详细介绍如何优雅地识别、解析和处理这个问题。
⭐️产生原因
详解导致 NullPointerException 的主要原因:
- 对空对象的属性或方法调用
- 未初始化的变量使用
- 数组未初始化访问
- 返回值为 null 的方法调用
⭐️优雅解析
为了更好地解析和定位 NullPointerException,我们可以采取以下步骤:
- 异常栈轨迹分析
- 可能为空的变量逐一排查
- 使用断言和条件检查
- 利用 Optional 类来处理可能为空的值
⭐️代码示例
优雅解决方案一:条件判断
使用条件判断,避免对可能为 null 的对象进行操作,从而消灭潜在的空指针异常。
import java.util.Optional;
public class NPEElimination {
public static void main(String[] args) {
// 解决方案一:条件判断
String name = null;
if (name != null) {
System.out.println("Hello, " + name + "!");
}
}
}
这种写法是比较丑陋的,为了避免上述丑陋的写法,让丑陋的设计变得优雅。JAVA8提供了Optional类来优化这种写法,接下来的正文部分进行详细说明
优雅解决方案二:断言与异常处理
合理运用断言和异常处理机制,增强代码健壮性,避免空指针问题在代码中蔓延。
import java.util.Optional;
public class NPEElimination {
public static void main(String[] args) {
// 解决方案二:断言与异常处理
String city = getCity();
assert city != null : "City should not be null";
System.out.println("City: " + city);
}
static String getCity() {
return "New York";
}
static String getUsername() {
return null;
}
}
优雅解决方案三:使用 Objects 类的 requireNonNull 方法
利用 Java 7 引入的 Objects 类提供的 requireNonNull 方法,实现更简洁的空指针检查。
import java.util.Objects;
public class RequireNonNullExample {
public static void main(String[] args) {
String city = null;
// 方案二:使用 requireNonNull 方法
city = Objects.requireNonNull(city, "City should not be null");
System.out.println("City: " + city);
}
}
优雅解决方案三:Optional 类的妙用
解析 Optional 源码: Optional 类是 Java 8 引入的一个用于处理可能为 null 的值的容器。它提供了丰富的 API,如 of、ofNullable、isPresent、ifPresent、orElse 等方法,能够帮助开发者优雅地处理可能为空的值,避免繁琐的空指针检查。
通过深入阅读 Optional 类的源码,你可以掌握以下核心概念:
1.内部属性:Optional 内部维护一个 value 属性,可以是实际的非空值,也可以是 null。
在 Optional
类中,value
属性是用于保存实际的非空值或者 null
的。该属性的类型为泛型 T
,表示可以保存任意类型的值。
源码解析: value
属性在 Optional
类中是一个 final
修饰的字段,用于保存实际的值。当 Optional
对象包含一个非空值时,value
属性将引用该值;当 Optional
对象为空时,value
属性为 null
。
以下是 Optional
类中的部分源码,展示了 value
属性的定义和初始化:
public final class Optional<T> {
// 实际的值,可以是非空值或者 null
private final T value;
// 构造方法,用于创建包含非空值的 Optional
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
// 构造空的 Optional
private Optional() {
this.value = null;
}
// ...
}
使用案例: 以下是一个示例,演示如何使用 Optional
的 value
属性来存储实际的非空值或者 null
:
import java.util.Optional;
public class ValueAttributeExample {
public static void main(String[] args) {
String name = "John";
// 创建包含非空值的 Optional
Optional<String> optionalName = Optional.of(name);
if (optionalName.isPresent()) {
System.out.println("Name: " + optionalName.get()); // 输出:Name: John
}
// 创建空的 Optional
Optional<String> emptyOptional = Optional.empty();
if (!emptyOptional.isPresent()) {
System.out.println("Empty Optional"); // 输出:Empty Optional
}
}
}
- of 和 ofNullable 方法:用于创建 Optional 对象,其中 of 方法要求传入非空值,而 ofNullable 方法可以接受可能为空的值。
Optional
类中的 of
和 ofNullable
方法是用于创建 Optional
对象的两种方式,它们分别对应于传入非空值和可能为空的值。让我们深入了解它们的源码和使用案例。
源码解析: of
和 ofNullable
方法在 Optional
类中是静态方法。它们用于创建包含指定值的 Optional
对象,其中 of
方法要求传入非空值,而 ofNullable
方法可以接受可能为空的值。
以下是 Optional
类中的部分源码,展示了 of
和 ofNullable
方法的定义和实现:
public final class Optional<T> {
// 静态方法,创建包含指定非空值的 Optional
public static<T> Optional<T> of(T value) {
return new Optional<>(value);
}
// 静态方法,创建包含指定值(可能为空)的 Optional
public static<T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
// ...
}
使用案例: 以下是一个示例,演示如何使用 of
和 ofNullable
方法来创建不同类型的 Optional
对象:
import java.util.Optional;
public class OfAndOfNullableExample {
public static void main(String[] args) {
String name = "John";
// 使用 of 创建包含非空值的 Optional
Optional<String> optionalName = Optional.of(name);
if (optionalName.isPresent()) {
System.out.println("Name: " + optionalName.get()); // 输出:Name: John
}
// 使用 ofNullable 创建包含可能为空的 Optional
String nullValue = null;
Optional<String> nullableOptional = Optional.ofNullable(nullValue);
if (!nullableOptional.isPresent()) {
System.out.println("Value is null"); // 输出:Value is null
}
}
}
- isPresent 方法:判断 Optional 对象是否包含非空值。
- ifPresent 方法:在包含非空值的情况下,执行传入的操作。
public final class Optional<T> {
//省略....
public boolean isPresent() {
return value != null;
}
//省略...
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
}
Optional.ofNullable(user)
.ifPresent(u->{
dosomething(u);
});
- orElse 方法:在 Optional 为空时,返回一个默认值。
orElse
方法是 Optional
类中常用的一个方法,用于在 Optional
为空时返回一个默认值。这可以有效地处理可能为空的情况,避免了空指针异常。
源码解析: orElse
方法的源码很简单,它接受一个参数作为默认值,如果 Optional
对象为空,则返回传入的默认值。
以下是 Optional
类中的部分源码,展示了 orElse
方法的定义和实现:
public final class Optional<T> {
// 返回值或默认值
public T orElse(T other) {
return value != null ? value : other;
}
// ...
}
使用案例: 以下是一个示例,演示如何使用 orElse
方法来处理可能为空的 Optional
,并提供一个默认值:
- filter 和 map 方法:用于对 Optional 内的值进行过滤和映射。
public final class Optional<T> {
//省略....
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
使用案例如下:
Optional<User> user1 = Optional.ofNullable(user).filter(u -> u.getName().length()<6);
- flatMap 方法:用于处理嵌套的 Optional,降低 Optional 嵌套层次。
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
使用案例如下:
// 使用 flatMap 处理嵌套的 Optional
String result = optionalBook.flatMap(Book::getAuthorName)
.orElse("Unknown Author");
- 空 Optional:Optional.empty() 表示空的 Optional。
源码解析: flatMap
方法的源码定义在 java.util.Optional
类中,其签名如下:
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
flatMap
方法接受一个函数 mapper
,该函数将原始 Optional
的值映射为另一个 Optional
,然后将嵌套的 Optional
展平为一个单层的 Optional
。如果原始 Optional
为空,或者 mapper
映射的 Optional
为空,那么 flatMap
返回一个空的 Optional
。
使用案例: 假设我们有一个场景,要从一本书的 Optional
中获取作者的名字,而作者的名字也被包装在一个 Optional
中。使用 flatMap
方法可以简洁地处理这种情况。
下面是一个示例代码,演示如何使用 flatMap
方法处理嵌套的 Optional
:
import java.util.Optional;
class Book {
private String authorName;
public Book(String authorName) {
this.authorName = authorName;
}
public Optional<String> getAuthorName() {
return Optional.ofNullable(authorName);
}
}
public class FlatMapExample {
public static void main(String[] args) {
Book book = new Book("John Doe");
Optional<Book> optionalBook = Optional.of(book);
// 使用 flatMap 处理嵌套的 Optional
String result = optionalBook.flatMap(Book::getAuthorName)
.orElse("Unknown Author");
System.out.println("Author: " + result);
}
}
⭐总结
通过本文的精彩演绎,你将彻底掌握解决 Java 空指针异常的多种优雅方法,在生产环境中我们可以通过Sonar 代码检测工具来检测代码问题,暴露出空指针所在位置,深入理解 Optional API 的精髓,助力你的代码更加健壮、可靠,从而成为更出色的 Java 开发者。
⏳ 名言警句:说会的,说对的
✨ 原创不易,还希望各位大佬支持一下
👍 点赞,你的认可是我创作的动力!
⭐️ 收藏,你的青睐是我努力的方向!
✏️ 评论,你的意见是我进步的财富!