前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >你有没有掉进去过这些 Exception 的“陷阱”(Part A)

你有没有掉进去过这些 Exception 的“陷阱”(Part A)

作者头像
RiemannHypothesis
发布2022-08-19 16:06:18
4140
发布2022-08-19 16:06:18
举报
文章被收录于专栏:Elixir

一、到底什么是空指针异常

空指针会出现在很多语言中,java中空指针异常指的是java.lang.NullPointException,我们都知道对象是保存在内存中的空指针异常中,空是内存地址为空,指针则是指该对象被别的对象指向或引用,当引用时就会爆出异常对象(引用数据类型)如果没有初始化操作就是null,这就是产生空指针异常的根本原因

image.png
image.png

二、常见空指针异常

新建maven项目 exception-traps,增加junit和lombok依赖

代码语言:javascript
复制
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.24</version>
    <scope>provided</scope>
</dependency>

创建com.lilith.traps.entity包,新增User实体类

代码语言:javascript
复制
@Data
public class User {

    public String name;
    public String[] books;

    public String say(){
        System.out.println("say()方法被调用了");
        return null;
    }

    public void readBook(){
        System.out.println("readBook()方法被调用了");
    }
}

现象1:访问了空对象的成员方法

在test包下创建com.lilith.traps.NullPointExceptionTest测试类

代码语言:javascript
复制
public class NullPointExceptionTest {

    @Test
    public void testCallNullObjMethod(){
        User user = null;
        user.readBook();
    }
}

在测试类中调用testCallNullObjMethod(),控制台打印空指针异常

image.png
image.png

现象2:调用了空对象的属性

在NullPointExceptionTest中增加方法testCallNullObjAttr(),测试空指针时调用对象属性

代码语言:javascript
复制
@Test
public void testCallNullObjAttr(){
    User user = null;
    user.getName();
}

在测试类中执行testCallNullObjAttr(),控制台打印空指针异常

image.png
image.png

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

代码语言:javascript
复制
@Test
public void testGetLenOfNullList(){
    User user = new User();
    System.out.println(user.books.length);
}

testGetLenOfNullList(),控制台打印空指针异常

image.png
image.png

现象4:抛出空的运行时异常

新增exception包,新增自定义运行时异常类LilithException,并继承RuntimeException

代码语言:javascript
复制
public class LilithException extends RuntimeException {
}

在NullPointExceptionTest测试类中新增方法testThrowNullException()

代码语言:javascript
复制
@Test
public void testThrowNullException(){
    LilithException lilithException = null;
    throw lilithException;
}

执行testThrowNullException(),抛出空指针异常

image.png
image.png

现象5: 对方法返回的空对象进行操作

在NullPointExceptionTest测试类中新增方法testHandleNullObjectOfMethodReturn()

代码语言:javascript
复制
@Test
public void testHandleNullObjectOfMethodReturn(){
    User user = new User();
    System.out.println(user.say().concat("Hello"));
}

执行testHandleNullObjectOfMethodReturn(),控制台打印出空指针异常

image.png
image.png

如何避免空指针异常

  • 使用对象之前一定要进行初始化,或者对是否初始化进行校验
  • 不要设置函数返回值为null
  • 针对接收的对象一定要进行判断

三、自动拆箱空指针异常

现象6:赋值时自动拆箱出现空指针异常

Java中的8中基本数据类型都会对应一个包装类

  • 装箱:基本类型转变为包装器类型的过程,装箱是通过调用包装器类的 valueOf 方法实现的
  • 拆箱:包装器类型转变为基本类型的过程,拆箱是通过调用包装器类的 xxxValue 方法实现的,xxx代表对应的基本数据类型。
image.png
image.png

自动拆箱引发的空指针:

  • 变量赋值自动拆箱引发空指针
  • 方法传递参数自动拆箱引发空指针

现象7:变量赋值时自动拆箱的空指针异常

在test包下新建UnboxingNullPointExceptionTest,新增testAssignValueWhenUnboxing()方法

代码语言:javascript
复制
public class UnboxingNullPointExceptionTest {

    @Test
    public void testAssignValueWhenUnboxing(){
        Long count = null;
        long count_ = count;
        System.out.println(count_);
    }
}

调用testAssignValueWhenUnboxing()方法,控制台打印出空指针报错信息

image.png
image.png

现象8:方法传参时自动拆箱空指针异常

在UnboxingNullPointExceptionTest测试类中定义一个add()方法,传入两个基本类型的x和y,新建测试方法testInputArgumentsByUnboxing(),在方法中调用add方法,并传入包装类

代码语言:javascript
复制
public static int add(int x, int y){
    return x + y;
}

@Test
public void testInputArgumentsByUnboxing(){
    Integer x = null;
    Integer y = null;
    add(x, y);
}

调用testInputArgumentsByUnboxing()方法,控制台打印报错信息如下

image.png
image.png

现象9:大小比较时自动拆箱空指针异常

在UnboxingNullPointExceptionTest测试类中定义一个compare()方法,传入两个基本类型的x和y,新建测试方法testCompareValueByUnboxing(),在方法中调用compare方法,并传入包装类

代码语言:javascript
复制
public static boolean compare(int x, int y){
    return x >= y;
}

@Test
public void testCompareValueByUnboxing(){
    Integer x = 1;
    Integer y = null;
    compare(x, y);
}

执行testCompareValueByUnboxing()方法

image.png
image.png

规避空指针异常的建议

拆箱是通过调用包装器类的 xxxValue 方法实现的,也就是说当包装类为空时调用方法就会出现空指针异常

  • 基本数据类型和引用数据类型,优先考虑基本数据类型
  • 对于不确定的包装器类型进行判断校验
  • 对于值为null的包装类赋值为0

四、String、ArrayList 的空指针情况

现象10:字符串使用equals()方法比较时空指针

新建测试类StringNullPointExceptionTest,新增测试方法testStringEqual()

代码语言:javascript
复制
public class StringNullPointExceptionTest {

    @Test
    public void testStringEqual(){
        String name = null;
        System.out.println(name.equals("stark"));
    }
}

执行该方法

image.png
image.png

控制台打印出空指针异常,这种情况就相当于与空对象调用属性,所以会出现空指针异常

非null字符串与可能为null的字符串使用equals()方法比较时,应该将可能为null的字符串放在equals()方法参数中,才能够进行比较,将最后一句代码替换为

代码语言:javascript
复制
System.out.println("stark".equals(name));

再次执行

image.png
image.png

控制台正常

现象11:操作对象数组中的空对象时空指针

在测试类中新增测试类ListNullPointExceptionTest,增加测试方法testHandleNullElementOfList()

代码语言:javascript
复制
public class ListNullPointExceptionTest {

    @Test
    public void testHandleNullElementOfList(){
        User[] userList = new User[5];
        for (int i = 0; i < 4; i++) {
            userList[i].name = "Mark " + i;
        }
    }
}

执行该方法

image.png
image.png

userList[i] 为null,通过.属性的方式赋值会报错空指针

现象12:ArrayList执行addAll(null)时空指针

在ListNullPointExceptionTest测试类中新增方法

代码语言:javascript
复制
@Test
public void testAddNullElementToList(){
    List<User> userList = new ArrayList<>();
    Collection<User> users = null;
    userList.addAll(users);
}

执行该方法

image.png
image.png

控制台出现空指针异常

查看ArrayList的addAll()方法的源码

image.png
image.png

这里使用了toArray()方法,由于参数本身是null,所以执行会报错

image.png
image.png
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-12-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、到底什么是空指针异常
  • 二、常见空指针异常
    • 现象1:访问了空对象的成员方法
      • 现象2:调用了空对象的属性
        • 现象3:当数组是一个空对象的时候,取它的长度
          • 现象4:抛出空的运行时异常
            • 现象5: 对方法返回的空对象进行操作
              • 如何避免空指针异常
              • 三、自动拆箱空指针异常
                • 现象6:赋值时自动拆箱出现空指针异常
                  • 现象7:变量赋值时自动拆箱的空指针异常
                    • 现象8:方法传参时自动拆箱空指针异常
                      • 现象9:大小比较时自动拆箱空指针异常
                        • 规避空指针异常的建议
                        • 四、String、ArrayList 的空指针情况
                          • 现象10:字符串使用equals()方法比较时空指针
                            • 现象11:操作对象数组中的空对象时空指针
                              • 现象12:ArrayList执行addAll(null)时空指针
                              领券
                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档