自定义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
相关产品推荐
相关产品推荐

