• 常见的NullPointerException总结


    NullPointerException在这里简称为NPE

    通过一些实例总结下常见的NPE问题:

    1. 自动拆箱抛NPE

    实体类:

     1 public class User {
     2     private String name;
     3     private Integer age;
     4     
     5     public String getName() {
     6         return name;
     7     }
     8     public void setName(String name) {
     9         this.name = name;
    10     }
    11     public Integer getAge() {
    12         return age;
    13     }
    14     public void setAge(Integer age) {
    15         this.age = age;
    16     }
    17     @Override
    18     public String toString() {
    19         return "User [name=" + name + ", age=" + age + "]";
    20     }
    21 }

    测试类:

     1 public class NPEDemo {
     2 
     3     public static void main(String[] args) {
     4         method();
     5     }
     6     
     7     static int method(){
     8         User user = new User();
     9         System.out.println("---" + new User().toString());
    10         return  user.getAge();
    11     }
    12 }

    出错:

    ---User [name=null, age=null]
    Exception in thread "main" java.lang.NullPointerException
        at finaldemo.NPEDemo.method(NPEDemo.java:12)
        at finaldemo.NPEDemo.main(NPEDemo.java:6)

    分析错误原因:

    包装类型为 null 时,进行自动转换为基本数据类型报错。

    return user.getAge();

    其中user不为空,但是user.getAge()为空(Integer类型)

    而且method方法需要的返回类型是int,此时就自动进行了拆箱转换,即从Integer到int类型的转换。

    而从Integer到int类型转换的时候user.getAge().intValue(); 会报空指针异常

    解决方案:

    返回之前进行判断与处理或者改为相同类型。

    2. 级联调用易产生NPE

    这段代码有点容易迷惑人,因为它进行了集合元素的 isEmpty 判断,按说不会出问题了吧。看代码:

     1 static void method1() {
     2     List<User> list = new ArrayList<User>();
     3     list.add(new User());
     4 
     5     if (!CollectionUtils.isEmpty(list)) {
     6         for (User user : list) {
     7             System.out.println("userid:" + user.getAge().toString());
     8         }
     9     }
    10 }

    报错:

    Exception in thread "main" java.lang.NullPointerException
        at finaldemo.NPEDemo.method1(NPEDemo.java:18)
        at finaldemo.NPEDemo.main(NPEDemo.java:9)

    分析错误原因:

    其实就是尽管你在之前做了对象不为空的判断,但你并不能保证对象中的值不为空,而且这时候去级联调用就会抛 NPE 。

    手册中关于 NPE 的描述:

    防止 NPE 是调用者的责任。即使被调用方法返回空集合或者空对象,对调用者来说,也并非高枕无忧,必须考虑到远程调用失败、序列化失败、运行时异常等场景返回 null 的情况。 集合里的元素即使 isEmpty,取出的数据元素也可能为 null。 级联调用 obj.getA().getB().getC();一连串调用,易产生 NPE

    3. 关于 Equals
    这是日常开发中用于相等比较使用最多的方法了吧,因为当年谁没被 == 坑过阿。现在一般我们都会这么写:

     1 public class NPEDemo {
     2 
     3     public static void main(String[] args) {
     4         method1();
     5     }
     6     
     7     static void method1() {
     8         User user = new User();
     9         user.getName().equals("men");
    10     }
    11 }

    分析错误原因:

    一不小心使用了 null 值调用了 Equals 方法。

     解决方案:

    很简单咯,这么写:"mafly".equals(user.getName());

    equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。

     4.Map 下的 NPE
    Map 应该是我们开发中使用最频繁的了,最常用的可能有 HashMapConcurrentHashMap 这俩了,可能会一不留神写出这样的代码:

     1 public class NPEDemo {
     2 
     3     public static void main(String[] args) {
     4         method1();
     5     }
     6     
     7     static void method1() {
     8         User user = new User();
     9         Map<Integer, Object> map = new HashMap<Integer, Object>();
    10         map.put(user.getAge(), user.getName());
    11         // System.out.println("---" + map);
    12         Map<Integer, Object> map2 = new ConcurrentHashMap<Integer, Object>();
    13         map2.put(user.getAge(), user.getName());
    14         
    15     }
    16 }

    报错:

    Exception in thread "main" java.lang.NullPointerException
        at java.util.concurrent.ConcurrentHashMap.put(Unknown Source)
        at finaldemo.NPEDemo.method1(NPEDemo.java:21)
        at finaldemo.NPEDemo.main(NPEDemo.java:12)

    分析错误原因:

    可能我们知道 ConcurrentHashMap 的 K/V 都不能为空,但我们有时候并不知道传进来的值是否为空。

    解决方案:

     设置时做下检验,对它的特性正确理解及使用。

    由于 HashMap 的干扰,很多人认为 ConcurrentHashMap 是可以置入 null 值,而事实上, 存储 null 值时会抛出 NPE 异常

    Map 类集合 K/V 能不能存储 null 值的情况,如下表格:

    集合类KeyValueSuper说明
    Hashtable 不允许为 null 不允许为 null Dictionary 线程安全
    ConcurrentHashMap 不允许为 null 不允许为 null AbstractMap 分段锁技术
    TreeMap 不允许为 null 允许为 null AbstractMap 线程不安全
    HashMap 允许为 null 允许为 null AbstractMap 线程不安全
  • 相关阅读:
    常数时间国密算法
    A Guide to the Go Garbage Collector
    并发控制 互斥
    词典遍历顺序
    max size of IPv4 & IPv6 packet 包大小
    BufferOverflow Attacks
    unsigned 是表示无符号数据类型,
    回溯 递归 的回退状态
    抖音平台多产物代码隔离技术的实践与探索
    依赖注入 开发效率
  • 原文地址:https://www.cnblogs.com/happy520/p/6925367.html
Copyright © 2020-2023  润新知