解决 java.util.Iterator java.util.List.iterator()' on a null object reference 异常的办法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/willway_wang/article/details/85724737

前言

最近,负责解决线上捕获的 bug,其中一个就是 java.util.Iterator java.util.List.iterator()’ on a null object reference 问题。很明显这样的异常是由于遍历了一个为 null 的集合导致的。难道我们仅仅对集合进行判空处理就可以了吗?

正文

代码示例

先说一下我自己的代码情况,代码示例如下:
需要的两个 bean 类:

// 垃圾类
public class RubbishBean {
    private String mName;

    public RubbishBean(String name) {
        mName = name;
    }

    public String getName() {
        return mName == null ? "" : mName;
    }

    public void setName(String name) {
        mName = name;
    }

    @Override
    public String toString() {
        return "RubbishBean{" +
                "mName='" + mName + '\'' +
                '}';
    }
}
// 垃圾类别类
public class RubbishCategory {
    private String mType;
    private List<RubbishBean> mRubbishBeanList;

    public RubbishCategory(String type, List<RubbishBean> rubbishBeanList) {
        mType = type;
        mRubbishBeanList = rubbishBeanList;
    }

    public String getType() {
        return mType == null ? "" : mType;
    }

    public void setType(String type) {
        mType = type;
    }

    public List<RubbishBean> getRubbishBeanList() {
        return mRubbishBeanList;
    }

    public void setRubbishBeanList(List<RubbishBean> rubbishBeanList) {
        mRubbishBeanList = rubbishBeanList;
    }
}

测试代码如下:

List<RubbishCategory> rubbishCategoryList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
    List<RubbishBean> rubbishBeans = null;
    rubbishBeans = new ArrayList<>();
    rubbishBeans.add(new RubbishBean("rubbishbean" + i));
    rubbishCategoryList.add(new RubbishCategory("type" + i, rubbishBeans));
}
for (RubbishCategory rubbishCategory : rubbishCategoryList) {
    List<RubbishBean> rubbishBeanList = rubbishCategory.getRubbishBeanList();
    for (RubbishBean rubbishBean : rubbishBeanList) {
        Log.d("tag",rubbishBean.toString());
    }
}

代码很简单,先初始化集合,再遍历集合。运行一下,查看日志:

D/tag: RubbishBean{mName='rubbishbean0'}
D/tag: RubbishBean{mName='rubbishbean1'}
D/tag: RubbishBean{mName='rubbishbean2'}
D/tag: RubbishBean{mName='rubbishbean3'}
D/tag: RubbishBean{mName='rubbishbean4'}

可以看到,这是没有问题的。
那么,现在修改一下代码:

List<RubbishCategory> rubbishCategoryList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
    List<RubbishBean> rubbishBeans = null;
    if (i != 3) {
        rubbishBeans = new ArrayList<>();
        rubbishBeans.add(new RubbishBean("rubbishbean" + i));
    }
    // 当是第 4 个元素时,就不再初始化 rubbishBeans,也就是让它仍然为 null。
    rubbishCategoryList.add(new RubbishCategory("type" + i, rubbishBeans));
}
for (RubbishCategory rubbishCategory : rubbishCategoryList) {
    List<RubbishBean> rubbishBeanList = rubbishCategory.getRubbishBeanList();
    for (RubbishBean rubbishBean : rubbishBeanList) {
        Log.d("tag", rubbishBean.toString());
    }
}

改动的地方,查看上面的注释。运行一下,查看日志:

 E/AndroidRuntime: FATAL EXCEPTION: main
 Process: com.wzc.myblogdemos, PID: 24371
 java.lang.NullPointerException: Attempt to invoke interface method 'java.util.Iterator java.util.List.iterator()' on a null object reference

这不正是我们要分析的报错吗?

优化1

可以修改 RubbishCategory 类中的 mRubbishBeanList 字段的 getter 方法,来避免这一异常:

public List<RubbishBean> getRubbishBeanList() {
    return mRubbishBeanList != null ? mRubbishBeanList : new ArrayList<RubbishBean>();
}

再次运行代码,查看日志:

D/tag: RubbishBean{mName='rubbishbean0'}
D/tag: RubbishBean{mName='rubbishbean1'}
D/tag: RubbishBean{mName='rubbishbean2'}
D/tag: RubbishBean{mName='rubbishbean4'}

报错不见了,可以正常打印出结果了。只是没有了第 4 个元素。

优化2

但是,在实际开发中,我却发现自己确实给mRubbishBeanList 集合赋值了,怎么在遍历的时候会取到 null 值呢?这种情况,我不能演示出来。推测是RubbishCategorymRubbishBeanList 字段的 setter 方法出现的问题,请看这个 setter 方法:

public void setRubbishBeanList(List<RubbishBean> rubbishBeanList) {
    mRubbishBeanList = rubbishBeanList;
}

把扫描数据库获取到的 RubbishBean 的集合赋值给 RubbishCategory 对象的 mRubbishBeanList 字段,也就是说,让 mRubbishBeanList 字段指向扫描数据库获取到的 RubbishBean 的集合。这里有什么问题吗?
是的,假如扫描数据库获取到的 RubbishBean 的集合被置为 null 了,那么 mRubbishBeanList 字段不也为 null 了吗?这种情况是有可能发生的。
那么,如何避免这一情况呢?优化 setter 方法:

private List<RubbishBean> mRubbishBeanList = new ArrayList<>();
public void setRubbishBeanList(List<RubbishBean> rubbishBeanList) {
    if (rubbishBeanList != null) {
        mRubbishBeanList.clear();
        mRubbishBeanList.addAll(rubbishBeanList);
    }
}

这样就可以有效避免上面异常的发生。

最后

记录开发中遇到的一个问题,希望能够帮助大家。另外,上面出现的异常,如果在 main 方法中演示,打印的异常是:

Exception in thread "main" java.lang.NullPointerException

远没有在 Android 环境下,打印出的异常丰富。这一点,也是我测试中发现的。

猜你喜欢

转载自blog.csdn.net/willway_wang/article/details/85724737