java.lang.NullPointerException 常见问题|Java Debug笔记

简介: java.lang.NullPointerException 常见问题|Java Debug笔记

一、问题描述:


java.lang.NullPointerException 是我们常见的开发问题之一,下面来看看大家进场容易犯的几种错误。


  1. 访问空对象的属性


image.png


  1. 空属性进行 equalshashcode 或者其他对象方法调用


image.png


  1. 将 null 传递给基础类型的方法入参数


image.png


调用方法


public static void test(int userId) {
    System.out.println(userId);
}


二、解决方法:


通用的解决方式有 3 种,分别是增加 if 判断,Optional 判断,或者增加编译 @NonNull 注解。


增加 if 判断,判断逻辑是 对象 != null && 对象.属性 != null


  1. 具体代码如下:


UserDto userDto = new UserDto();
if (userDto != null && Objects.equals(userDto.getUserId(), 1)) {
    test(userDto.getUserId());
}


这个办法看上去比较复杂,其实非常严谨、简单。如果项目中非常多类似的判断可以做通用的方法风封装比如 IntegerUtilStringUtil。还可以做一些定制化的逻辑,防止后期批量修改,减少代码改动。其实我们开发中也用到的三方的工具包如:hutool-utilapache-common


通过 Optional 判断, 如果不为空才执行调用方法,或者返回默认值


  1. 具体代码如下:


// 不为空才执行
UserDto userDto = new UserDto();
Optional.of(userDto.getUserId()).ifPresent(item -> {
    test(userDto.getUserId());
});
// 如果为空返回默认值
Integer userId = Optional.of(userDto.getUserId()).orElse(1);


Java 8 引入 Optional 类, 主要解决的问题是臭名昭著的空指针异常   (NullPointerException)。 这是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空,提供了非常多的实用方法比如:ifPresentorElse 。 Optional 是 Java 实现函数式编程的基石, 也是 Java 8 带来的一个非常优秀语法糖。


增加编译 @NonNull 注解 (org.springframework.lang.NonNull)


  1. 代码如下:


public static void test(@NonNull Integer userId) {
    System.out.println(userId);
}


我一般提供公共方法,或者一些调用方法的时候,都会通过 NonNullNullable去标记这个参数是否可以为空,这样可以方便的在我第调用的时候一目了然是否可以为空,而且如果传递参数为空,idea 会在编译的时候有提示的,非常方便。 还有就是对于 web api 接口的参数我们可以通过 jsr303 的一些注解去标注,是否为空,然后通过 @Vaild 去执行也是非常方便的。比如:Spring MVCHibernate Validator 都提供了丰富的参数检验库。特殊的我们也可以自己去定义。


三、总结:


本文比较简单和直观的描述了常见的几种 java.lang.NullPointerException 场景和解决方案。如果大家有也有类似的经历可以留言探讨


对于 NullPointerException 异常往往是在运行时的,可能我们去 select 一条数据,但是这个字段是非必填的,但是我们在查询的时候没有做 mapping 映射到 entity 也会出现 NullPointerException 。 所以大家对于代码逻辑的检查,很多时候都需要做一个折中的选择,其实在项目中只要能够找到这个平衡就好。


相关文章
|
14天前
|
Java
Java基础—笔记—static篇
`static`关键字用于声明静态变量和方法,在类加载时初始化,只有一份共享内存。静态变量可通过类名或对象访问,但推荐使用类名。静态方法无`this`,不能访问实例成员,常用于工具类。静态代码块在类加载时执行一次,用于初始化静态成员。
10 0
|
14天前
|
Java API 索引
Java基础—笔记—String篇
本文介绍了Java中的`String`类、包的管理和API文档的使用。包用于分类管理Java程序,同包下类无需导包,不同包需导入。使用API时,可按类名搜索、查看包、介绍、构造器和方法。方法命名能暗示其功能,注意参数和返回值。`String`创建有两种方式:双引号创建(常量池,共享)和构造器`new`(每次新建对象)。此外,列举了`String`的常用方法,如`length()`、`charAt()`、`equals()`、`substring()`等。
15 0
|
1月前
|
算法 搜索推荐 Java
数据结构与算法(Java篇)笔记--希尔排序
数据结构与算法(Java篇)笔记--希尔排序
|
2月前
|
监控 负载均衡 Dubbo
|
3月前
|
存储 安全 算法
详解Java中HashMap、HashTable、ConcurrentHashMap常见问题
详解Java中HashMap、HashTable、ConcurrentHashMap常见问题
44 0
|
14天前
|
Java API
Java基础—笔记—内部类、枚举、泛型篇
本文介绍了Java编程中的内部类、枚举和泛型概念。匿名内部类用于简化类的创建,常作为方法参数,其原理是生成一个隐含的子类。枚举用于表示有限的固定数量的值,常用于系统配置或switch语句中。泛型则用来在编译时增强类型安全性,接收特定数据类型,包括泛型类、泛型接口和泛型方法。
9 0
|
1月前
|
算法 搜索推荐 Java
数据结构与算法(Java篇)笔记--快速排序
数据结构与算法(Java篇)笔记--快速排序
|
1月前
|
机器学习/深度学习 算法 搜索推荐
数据结构与算法(Java篇)笔记--归并排序
数据结构与算法(Java篇)笔记--归并排序
|
1月前
|
算法 搜索推荐 Java
数据结构与算法(Java篇)笔记--插入排序
数据结构与算法(Java篇)笔记--插入排序
|
1月前
|
算法 搜索推荐 Java
数据结构与算法(Java篇)笔记--选择排序
数据结构与算法(Java篇)笔记--选择排序