1

Suppose I have two classes SuperClass and SubClass which extends SuperClass, such as below:

public abstract class SuperClass {
    private Object field1;

    protected SuperClass(Object obj) {
        setField1(obj);
    }

    public void setField1(Object obj) {
        // perform some check on obj and
        // then set field1 such that field1==obj
    }
}


public class SubClass extends SuperClass {
    public SubClass(Object obj) {
        super(obj);
    }

    @Override
    public void setField1(Object obj) {
        super.setField1(obj);
        // do some work that is necessary only when
        // field1 is set through SubClass.setField1()
    }
}

What I need is, when I create an object of SubClass, I need method SuperClass.setField1() to be called from inside SuperClass constructor, not SubClass.setField1(). But with the above code, method SubClass.setField1() is called which causes a NullPointerException to be thrown, since the work done in SubClass.setField1() is performed on a field that's yet null.

Is there any way to explicitly call SuperClass.setField1()‍‍‍ from inside SuperClass constructor?

  • Relevant: https://stackoverflow.com/questions/4595512/java-calling-a-super-method-which-calls-an-overridden-method#4595762 – kabanus Jul 29 '18 at 11:51
  • Possible duplicate of [Java Polymorphism How to call to super class method for subclass object](https://stackoverflow.com/questions/14907424/java-polymorphism-how-to-call-to-super-class-method-for-subclass-object) – ernest_k Jul 29 '18 at 11:53
  • 1
    Why does it cause ```NullPointerException``` to be thrown? – zhh Jul 29 '18 at 11:54
  • 1
    @zhh Because the additional work in overridden method is performed on fields that are declared in `SubClass` and are not instantiated yet, since the `super` command must be called first of all, in `SubClass` constructor. – Hedayat Mahdipour Jul 29 '18 at 11:57
  • 1
    From which line NullPointerException is coming? Can you please paste the whole code how you are invoking the constructor and which parameters you are passing to it? – Rahul Vedpathak Jul 29 '18 at 11:59
  • I think we can find a solution as requested, but actually your problem arises from calling a polymorphous method from a constructor. This is discouraged in Java (because such strange effects can occur). Use e.g. a static factory to work around this - and you will not have to solve this problem. Do you need help for the static factory? – CoronA Jul 29 '18 at 12:02
  • 1
    [Calling overrideable methods from inside a constructor is well-known to be dangerous](https://stackoverflow.com/q/3404301/3788176). Just don't do it. – Andy Turner Jul 29 '18 at 12:16
  • @CoronA I'm familiar with static factories. But I'm not sure if this can be applied to my example. In my actual program, the SuperClass corresponds to an abstract class called `MilitaryUnit` which has a field `graphic` (corresponding to `field1`). And a subclass called `MovableUnit` which introduces the additional field `animation` that applies to `graphic` to move it. In class `MovableUnit` when `super()` is called, there's no animation yet, but it calls method `setGraphic()`. Every time a new `graphic` is set, it must be introduced to `animation` in method `MovableUnit.setGraphic()`. – Hedayat Mahdipour Jul 29 '18 at 12:19
  • @CoronA I'm not sure if I could explain the situation clearly. – Hedayat Mahdipour Jul 29 '18 at 12:20
  • It would be best if you add some code the reproduces the problem. I understand why a static factory is not applicable, but yet I do not understand why you call `setField` in your constructor. Just copy and paste the contents of `setField`, not every copy and paste is bad. – CoronA Jul 29 '18 at 12:27

1 Answers1

2

You could move said method body to a private method and let the default method (the one which may be overridden by the subclass) delegate to the former. See this example

public abstract class SuperClass {

    private Object field1;

    protected SuperClass(Object obj){
        // call the safe implementation
        setField1Safe(obj);
    }


    public void setField1(Object obj){
        // just delegates
        setField1Safe(obj);
    }

    private void setField1Safe(Object obj){
        // perform some check on obj and
        // then set field1 such that field1==obj
    }
}

public class SubClass extends SuperClass{
     public SubClass(Object obj){
         super(obj);
     }

     @Override
     public void setField1(Object obj){
         super.setField1(obj);
         // do some work that is necessary only when
         // field1 is set through SubClass.setField1()
     }
}

That way the sub class can still override setField1 but if you really depend on the implementation then you can call the private setField1Safe method.

Lino
  • 19,604
  • 6
  • 47
  • 65
  • if he is gonna make the method private then there will not be any method overriding .he is trying override the methods – JAMSHAID Jul 29 '18 at 12:32
  • 1
    I think Lino should rewrite his example and adjust it to the given one. I supect that the method `doStuff` is meant to be inherited while `doStuffButPrivate` is called from the constructor. – CoronA Jul 29 '18 at 14:38
  • @CoronA that's what I intended to tell with this, I've updated to reflect the changes OP should made in his code – Lino Jul 29 '18 at 18:08