首页>>后端>>java->Java中避免空指针的几个方法!

Java中避免空指针的几个方法!

时间:2023-12-02 本站 点击:0

Java 编程中哪个异常是你印象最深刻的,那 NullPointerException 空指针可以说是臭名昭著的。不要说初级程序员会碰到,即使是中级,专家级程序员稍不留神,就会掉入这个坑里。

Java 中任何对象都有可能为空,当我们调用空对象的方法时就会抛出 NullPointerException 空指针异常,这是一种非常常见的错误类型。我们可以使用若干种方法来避免产生这类异常,使得我们的代码更为健壮。

空指针出现的几种情况

1、调用了空对象的实例方法

publicclassPerson{//属性privateStringname;privateintage;publicvoidprint(){System.out.println("ThisisPersonClass");}publicStringread(){System.out.println("Thisispersonread");returnnull;}publicstaticvoidmain(String[]args){Personperson=null;//调用了空对象的实例方法person.print();}}

2、访问了空对象的属性

Personperson=null;//调用了空对象的属性System.out.println(person.age);

3、当数组是一个空对象时,取它的长度

Personperson=null;//当数组是一个空对象时,取它的长度System.out.println(person.name.length());

4、方法的返回值是 null, 调用方直接去使用

Personperson=newPerson();//方法的返回值是null,调用方直接去使用System.out.println(person.read().contains("Java"));

如何从根源避免空指针

1、使用之前一定要初始化,或检查是否初始化;

2、尽量避免在函数中返回 NULL, 或给出详细的注释;

3、外部传值,除非有明细的说明,否则,一定要判断是否为 NULL。

equals和equalsIgnoreCase()方法

Object类中的equals 方法在非空对象引用上实现相等关系,具有对称性 x.equals(y) 和 y.equals(x) 结果是一样的,但当x == null时会抛出空指针异常。

例如:

Stringx=null;Stringy="world";if(x.equals(y)){//java.lang.NullPointerException}if(y.equals(x)){//即便x是null也能避免NullPointerException}

所以我们要把确定不为null的对象或值放在前面。

valueOf()和toString()

调用null对象的toString()会抛出空指针异常,使用valueOf()可以获得相同的值,传递一个 null 给 valueOf() 将会返回null。尤其是在那些包装类,像Integer、Float、Double和BigDecimal。

例如:

Integeri=null;System.out.println(i.toString());//抛出NullPointerException异常System.out.println(String.valueOf(i));//返回null不会出现异常

Optional 类型

Java 8 引入了 Optional类型,我们可以用它来对函数的返回值进行包装。这种方式的优点是可以明确定义该方法是有可能返回空值的,因此调用方必须做好相应处理,这样也就不会引发空指针异常。但是,也不可避免地需要编写更多代码,而且会产生很多垃圾对象,增加 GC 的压力,因此在使用时需要酌情考虑。

在业务系统中,对象中嵌套对象是经常发生的场景,如下示例代码:

//最外层对象classOuter{Nestednested;NestedgetNested(){returnnested;}}//第二层对象classNested{Innerinner;InnergetInner(){returninner;}}//最底层对象classInner{Stringfoo;StringgetFoo(){returnfoo;}}

业务中,假设我们需要获取 Outer 对象对底层的 Inner 中的 foo 属性,我们必须写一堆的非空校验,来防止发生 NullPointerException

//繁琐的代码Outerouter=newOuter();if(outer!=null&&outer.nested!=null&&outer.nested.inner!=null){System.out.println(outer.nested.inner.foo);}

在 Java8 中,我们有更优雅的解决方式,那就是使用 Optional是说,我们可以在一行代码中,进行流水式的 map 操作。而 map 方法内部会自动进行空校验:

Optional.of(newOuter()).map(Outer::getNested).map(Nested::getInner).map(Inner::getFoo.ifPresent(System.out::println);//如果不为空,最终输出foo的值

suppiler 函数自定义增强 API

我们可以利用 suppiler 函数来出一个终极解决方案:

publicstatic<T>Optional<T>resolve(Supplier<T>resolver){try{Tresult=resolver.get();returnOptional.ofNullable(result);}catch(NullPointerExceptione){//可能会抛出空指针异常,直接返回一个空的Optional对象returnOptional.empty();}}

利用上面的 resolve 方法来重构上述的非空校验代码段:

Personperson=null;//调用了空对象的属性System.out.println(person.age);0

使用null安全的方法和库

有很多开源库已经为您做了繁重的空指针检查工作。其中最常用的一个的是Apache commons 中的StringUtils。你可以使用StringUtils.isBlank()isNumeric()isWhiteSpace()以及其他的工具方法而不用担心空指针异常。

Personperson=null;//调用了空对象的属性System.out.println(person.age);1

断言

断言是用来检查程序的安全性的,在使用之前进行检查条件,如果不符合条件就报异常,符合就继续。

Java 中自带的断言关键字:assert,如:

Personperson=null;//调用了空对象的属性System.out.println(person.age);2

输出:

Personperson=null;//调用了空对象的属性System.out.println(person.age);3

不过默认是不启动断言检查的,需要要带上 JVM 参数:-enableassertions 才能生效。

Java 中这个用的很少,建议使用 Spring 中的,更强大,更方便好用。

Spring中的用法:

Personperson=null;//调用了空对象的属性System.out.println(person.age);4

创建返回空集合而不是null的方法

一个非常好的技术是创建返回一个空集合的方法,而不是一个null值。你的应用程序的代码可以遍历空集合并使用它的方法和字段,而不会抛出一个NullPointerException。Collections类提供了方便的空 List,Set 和 Map: Collections.EMPTY_LISTCollections.EMPTY_SETCollections.EMPTY_MAP

例如:

Personperson=null;//调用了空对象的属性System.out.println(person.age);5

赋值时自动拆箱出现空指针

1、变量赋值自动拆箱出现的空指针

Personperson=null;//调用了空对象的属性System.out.println(person.age);6

Long 自动拆箱为 long 实质是调用了 longValue 方法,由于以上的 Long 类型变量值为 null,自动拆箱就会报 NPE。

2、方法传参时自动拆箱引起空指针异常

Personperson=null;//调用了空对象的属性System.out.println(person.age);7

以上自动拆箱报 NPE,原因在于装箱的值为 null,调用 null 的任何 方法都会报错。

规避指南:

基本数据类型优于包装器类型,优先考虑使用基本类型。

对于不确定的包装器类型,一定要校验是否为 NULL。

基本数据类型比包装器类型更加节省时间与空间。

结语

关于怎么有效避免空指针,其实还有更多,如何避免空指针,一是要注意代码编写规范,二是要提高代码素养。我们一起加油~


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/java/10434.html