You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义View中final成员变量触发NullPointerException问题排查

自定义View中Map成员空指针异常问题

问题描述

我在创建自定义View时编写了如下代码,其中icon是声明时直接初始化的final Map,但在onInit方法中调用icon.put()时抛出了NullPointerException,提示调用put方法的对象是null:

public class TestView extends BaseCustomView<ViewTestBinding> {
    ...
    @NonNull
    private final Map<Boolean, Drawable> icon = new HashMap<>();

    private void onInit(Context context, @Nullable TypedArray attrs) {
        assert attrs != null;
        // 此处抛出NullPointerException
        icon.put(true, attrs.getDrawable(R.styleable.TestView_icon));
        icon.put(false, attrs.getDrawable(R.styleable.TestView_iconUnselect));
        ...
    }
}

onInit方法会在每个构造函数中被调用,抛出的异常信息如下:

java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object java.util.Map.put(java.lang.Object, java.lang.Object)' on a null object reference

我认为icon不可能被置为null,想知道为何会抛出该异常。


问题复现与疑问(2022/11/18 14:48 GMT+8)

根据提示编写了简化测试用例,成功复现了类似问题:当成员变量是包装类型Integer时,输出null;改成基本类型int时,输出设定的初始化值。

测试代码如下:

public class ExampleUnitTest {
    @Test
    public void test() {
        new ClassB();
    }

    public static abstract class ClassA {
        public ClassA() {
            method();
        }

        protected abstract void method();
    }

    public static class ClassB extends ClassA {
        @SuppressWarnings("FieldCanBeLocal")
        private final Integer integer = 114514; // 输出null
//        private final int integer = 114514; // 输出114514

        @Override
        protected void method() {
            System.out.println(integer);
        }
    }
}

我仍有以下疑问:

  • 我是在成员变量定义时直接赋值,而非在构造函数中初始化,为何还是会出现Integer输出null的情况?是不是直接初始化的赋值操作实际是在子类构造函数中执行?
  • 如果赋值操作确实在子类构造函数中执行,那改成int类型时应该输出默认值0,但实际却输出了我设定的初始化值,这该如何解释?

内容的提问来源于stack exchange,提问作者Madray Haven

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 21:15:32