I'm creating a custom view, and I write code like this:
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 throws at this line
icon.put(true, attrs.getDrawable(R.styleable.TestView_icon));
icon.put(false, attrs.getDrawable(R.styleable.TestView_iconUnselect));
...
}
Method onInit
will be called in every constructor, but when I store the key-value pair in the icon
, it thows NullPointerException:
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
I put the full code on Github. From my understanding, changing icon
to null is impossible, so why is NullPointerException thrown? Thank you!
Update (2022/11/18 14:48 GMT +8):
According to the answer of @Cheticamp, I write a minify test case: ExampleUnitTest.java, and it reproduced the error, System.out.println()
at line 31 printed null.
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; // print null
// private final int integer = 114514; // print 114514
@Override
protected void method() {
System.out.println(integer);
}
}
}
But I still can't understand why I got null, the code in this link initializes members in the constructor, and I assign the value directly after defining, Even if I initialize directly, is the actual assignment still performed in the subclass constructor?
If so, when I change the type to int
like line 27, it should print the int's initial value of 0, but this time it correctly prints the value I initialized.