1

I currently have 2 classes with the following structure (simplified here):

class A
{
  private List<String> myList = new ArrayList<>();

  public A()
  {
    init();
  }

  public void init()
  {
    myList.add("apple");
  }
}


class B extends A
{
  private List<String> myList = new ArrayList<>();
  public B()
  {
    super();
    init();
  }

  @Override
  public void init()
  {
    myList.add("apple");
  }
}

I observe that in A's init(), myList is of size 0, so it was able to add "apple". But in B's init(), myList is null, and it throws a NPE when trying to add "apple".

I know this might be something fundamental that I can't understand and I'd want to wrap my head around this.

Thanks in advance.

Edit: Happened to see this Why child private field is null when printing it from parent class using polymorphism in java? Is it dynamic binding? I have explicitly declared my ctor, moreover it's a list, don't they get automatically initiallized to empty lists?

user7999116
  • 199
  • 1
  • 12

1 Answers1

2

In general, subclass initialization doesn't happen until superclass initialization is complete, to avoid having the subclass implementation see superclass components in an inconsistent state. The initialization of B's myList field doesn't look like it's attached to any constructor, but it actually happens in any B constructor immediately after the superclass constructor call. This field is a completely separate field from the one declared by the superclass.

When A's constructor tries to call self.init, it gets the override from B. B's override tries to append to the private myList field in B, but that field isn't initialized yet.

It's generally best to avoid calling overrideable methods in a constructor.

user2357112
  • 260,549
  • 28
  • 431
  • 505