A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

在写代码的过程中,出现最多的异常可能就是空指针异常了。说白了,空指针异常就是你拿一个不存在的对象,去访问它的成员属性或者方法。我们暂且看下面的代码:
public static String getString() {    return null;}public static void main(String[] args) {    // 此处返回null    String str = getString();    System.err.println(str.length());}复制代码很明显,上面程序运行的结果肯定是排除烦人的java.lang.NullPointerException:
Exception in thread "main" java.lang.NullPointerException        at org.springframework.web.SpringServletContainerInitializer.main(SpringServletContainerInitializer.java:187)复制代码但是,其实空指针本身并不是那么可怕,可怕的是命名我们知道有这么一种可能会出现空指针异常,但是我们却不知道或者没法提前预判,就像上面的代码片段,在eclipse IDE中是没有任何提示的,如下图:


那么有什么办法我们可以提前预判到可能会抛出NullPointerException的代码块,然后做防空处理呢!答案是肯定的。下面我将介绍几种常见的防空方式,注意,这不是演习,这不是演习,这不是演习。哈哈!
  • 1、使用注解方式标识参数、方法返回值是否为空
  • 2、使用Java8提供的Optional类声明我们的API
下面我将一一举例进行探讨(IDE以eclipse为例):
前置处理:
首先我们要在eclipse启用基于注解的检查,在Windows->Preference->Java->Compiler->Errors/Warnings->Null Analysis,如下图所示:


一、使用注解方式标识参数、方法返回值是否为空JSR 303/305和Spring都提供了相应的的注解,如下所示:
  • 1、JSR 303/305:@Nonnull、@Nullable
  • 2、Spring:@NonNull、@Nullable
在eclipse启动空检验之后,要想使上面的@Nullable注解生效,还需要将注解的全路径类型配置到上图的Use default annotations for null sercifications,配置如下图:


配置完成之后,再看下面代码:
/** * 表示返回的值可能为空 * @return */@Nullablepublic static String getString() {    return null;}/** * 参数不能为空 * @param str * @return */public static String getName(@NonNull String str) {    return null;}public static void main(String[] args) {    // 此处返回null    String str = getString();    System.err.println(str.length());        // 参数为空    getName(null);}复制代码

这样子可能为空的代码就一目了然了。当然了,其中的原理还是IDE支持扫描JSR规范的相关注解,Spring的@NonNull、@Nullable也是基于JSR注解实现的,可用于声明方法,字段或者参数。
二、OptionalJava8提供了对null进行建模的类,它叫Optional。我们可以把它理解为一个容器,容器里保存的,可以是方法的放回值,也可以是方法参数值,如果方法返回值为null或者参数值为null,那么就返回一个空容器对象。请看下面代码:
/** * 表示返回的值可能为空 * @return */public static Optional<String> getString() {    // 返回空容器,里边什么也没有    return Optional.empty();}/** * 参数不能为空 * @param str * @return */public static String getName(Optional<String> str) {    return str.get();}public static void main(String[] args) {    // 此处返回Optional.empty()    Optional<String> optional = getString();    // 如果返回的是空容器,那么就返回orElse的值,否则,返回容器里的值    String value = optional.orElse("otherValue");    // 输出otherValue    System.err.println(value);        // 参数为空    getName(Optional.of("value"));}复制代码使用Optional类很方便对可能返回null的值进行建模,同时Optional里边提供了很多有用的方法允许我们传入一个lambda表达式进行处理,非常方便。
总结
  • 1、如果只是单纯想处理代码逻辑中可能出现的null异常,那么其实我觉得使用IDE结合注解的方式可能会更加方便一点,当然使用Optional也是可以的
  • 2、如果我们想提供一个对外的API,我认为将API的成员属性、方法返回值声明为Optional可能会更好一点,因为别人一看就知道,该API方法签名可能会返回空值,使用者只需要用一个Optional对接收即可!
  • 3、要想减少空异常,关键还得提升自己的编码能力!身正不怕影子斜。


【转载】
作者:拥抱心中的梦想
链接:https://juejin.im/post/5be2b0a0e51d4549d46dc1f2



3 个回复

倒序浏览
~(。≧3≦)ノ⌒☆
回复 使用道具 举报
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马