传媒公司做网站编辑_如何?,新品发布会ppt参考,wordpress 侧边栏修改,北京工装装饰公司排行榜在Java编程语言中#xff0c;NullPointerException#xff08;简称NPE#xff09;是一种常见的运行时异常#xff0c;当程序试图访问或操作一个还未初始化#xff08;即值为null#xff09;的对象引用时#xff0c;Java虚拟机就会抛出NullPointerException。如果我们在日…在Java编程语言中NullPointerException简称NPE是一种常见的运行时异常当程序试图访问或操作一个还未初始化即值为null的对象引用时Java虚拟机就会抛出NullPointerException。如果我们在日常开发中不能很好的去规避NPE那么可能因为数据或者其他问题就会导致线上问题。。。很烦。。。。
阿里巴巴开发手册规约中也说明防止NPE是程序员的基本素养。。。
接下来我们先谈谈几种可能会出现空指针异常的方式。
出现空指针异常的情况
访问空对象的属性或调用空对象的方法 当一个对象是null时试图访问一个对象的属性或调用其方法就会触发空指针异常。
String text null;
int length text.length();User user null;
String userName user.getUserName();数组为null或者数组元素为null 当尝试访问数组中的某个索引处的元素而该元素为null时同样会导致空指针异常。
String[] strs null;
int length strs.length;String[] strs new String[3];
int length strs[2].length();集合中null元素访问 当集合中存在null元素当我们遍历集合访问到这个元素的属性或者方法时也会抛出NPE这种情况也会出现在我们的日常开发中有时候就会因为数据问题导致这种情况发生常常也莫名其妙。。。。
ListString list Lists.newArrayList();
list.add(null);
System.out.println(list.get(0).length());调用的方法返回null 调用某个方法期望其返回一个非null的对象但实际返回了null。当然这种情况等同于访问空对象的属性或者方法。这在实际开发过程中极易出现的一种情况。比如我们使用Mybatis从数据库中查询一条记录时数据不存在就会返回null。这种情况尤为注意。
private User getUserInfo(){ return null;
}User user getUserInfo();
String userName user.getUserName();使用基本数据类型的包装类 在使用基本数据类型的包装类时如果未正确初始化再转成int时可能导致空指针异常。
Integer i null;
int num i;以上大概是我想到或者常遇到的一些可能会发生NPE的情况如果还有其他情况可以贴出来讨论。
那么我们该如何避免NPE呢
避免NPE的几种方式
访问对象前要谨慎 在使用对象之前始终检查它是否为null。这包括方法参数、返回值以及对象的属性。在访问对象的方法或属性之前使用条件语句判断对象是否为null。比如我们在访问User对象前一定要判null
User user new User();
if (user ! null){ String userName user.getUserName(); Address address user.getAddress(); if (address ! null){ String coutry address.getCountry(); }
}或者我们的user是从一个方法中获取的例如数据库中查询那么我们在访问这个对象前一定要判null如果为null要抛出对应的业务异常然后我们就可以在接口响应中对应返回错误的信息即可此时就算是一个正常的流程了。这点尤为重要一定要注意。
User user userManager.getUserById(Long userId);
if (user null){throw new ServiceException(当前查询的对象不存在);
}关于SpringBoot项目中捕获自定义业务异常统一异常管理统一结果返回可以参考这篇文章SpringBoot统一结果返回统一异常处理大牛都这么玩 | 码农Academy的博客 当然如果使我们在写User getUserById(Long id)返回对象或者ListUser listUserByIds(ListLong idList)时我们可以不返回null可以返回一个对象默认信息或者一个空集合这样调用方就不会出现NPE风险当然我们不强制返回一个对象或者空集合但是必须添加注释充分 说明什么情况下会返回null值。这也是阿里巴巴开发手册规约的建议。
使用Optional类 JDK8以上版本提供了Optional类它是一个容器对象可用于包装可能为null的值。我们可以使用它判断null问题同时也解决了多层级访问问题配合使用orElse时会先执行orElse方法然后执行逻辑代码不管是否出现了空指针。
String country Optional.ofNullable(user) .map(User::getAddress) .map(Address::getCountry) .orElse();String country Optional.ofNullable(user) .map(User::getAddress) .map(Address::getCountry) .orElseGet(() - defaultContry());private String defaultContry(){return CN;
}我们还可以使用orElseThrow()方法当Optional中的对象是一个null时我们直接抛出异常
String userName Optional.ofNullable(user).map(User::getUserName).orElseThrow(() - new ServiceException(当前用户信息不存在));使用断言避免空指针 使用Java断言assert来检查变量是否为null。但要注意断言通常在开发和测试阶段启用而在生产环境中可能被禁用在生产环境中通常不会启用断言以避免不必要的性能开销以及防止潜在的错误信息泄漏。
User user new User();
assert user ! null : user should not be null;
Address address user.getAddress();
assert address ! null : address should not be null;
String coutry address.getCountry(); 使用Nullable注解 使用javax.annotation.Nullable注解Nullable注解通常用于标记一个方法的参数、返回值或者字段可能为null。这个注解并非Java标准库的一部分但在一些第三方库如JSR 305库中的javax.annotation.Nullable以及Google Guava和JetBrains的Kotlin标准库等中广泛使用并且被许多IDE和静态分析工具支持。以便在编译期或开发工具中提示可能的NPE风险。
Nullable
private static User getUserById(Long userId){ return null;
} private static void handlerUser(Nullable User user){ System.out.println(user.getUserName());
}public static void main(String[] args) { Long userId 0L; User user getUserById(userId); String userName user.getUserName(); handlerUser(user);
}此时IDEA就会警告会出现NPE风险
借助工具扫描代码 在Java开发中我们还可以使用以下工具扫描代码以发现潜在的空指针异常风险。
IntelliJ IDEA内置了强大的静态代码分析器能够检测出可能的NPE和其他代码问题。SonarQube / SonarLint提供持续集成和本地IDE插件形式的静态代码分析能找出潜在的空指针以及其他质量或安全问题。Sonar可以定时扫描仓库中的代码可以发现代码中的一些潜在风险可以通过一些通知例如邮件等告知代码提交者这段代码的风险。FindBugs现更名为SpotBugs另一个开源的静态分析工具能够发现潜在的bug包括可能导致NPE的情况。阿里巴巴Java开发规约插件 对于Eclipse和IntelliJ IDEA都有相应的插件版本基于阿里巴巴内部Java编码规范包含了对可能出现NPE情况的检测。
补充一点
在JDK 17中引入的Helpful NullPointerExceptions特性确实增强了空指针异常信息的准确性与可用性。当发生NullPointerException时JVM现在能够提供更精确的位置信息特别是在链式调用场景下它会指出导致空指针异常的具体对象引用。这有助于开发者更快地定位到代码中的问题所在无需通过堆栈跟踪逐层分析来判断哪个对象引用为null。 假如我们访问user.getAddress().getCountry().length()时在JDK17以前如果发生了空指针异常他只会打印出来发生了空指针异常但是并没有告知到底是user对象还是address对象还是coutnry发生了异常
Exception in thread main java.lang.NullPointerExceptionat com.study.base.core.base.NpeTest.main(NpeTest.java:23)但是在JDK17以后借助Helpful NullPointerExceptions特性异常信息将更加精确可能会类似打印这样的信息精确到那个值发生了空指针异常
Exception in thread main java.lang.NullPointerException: Cannot invoke Address.getCountry() because user.address is nullat com.study.base.core.base.NpeTest.main(NpeTest.java:23)这又多了一个升级JDK到17以上的理由。
结论
NullPointerExceptionNPE是Java开发中常见的运行时异常源于对未初始化或已置为null的对象引用进行操作。在实际开发过程中进行非空检查、使用Optional类以及采用Null安全注解以及使用检查工具等策略可以有效避免此类异常的发生。
本文已收录于我的个人博客码农Academy的博客专注分享Java技术干货包括Java基础、Spring Boot、Spring Cloud、Mysql、Redis、Elasticsearch、中间件、架构设计、面试题、程序员攻略等。