Overriding Protected Superclass Method

The example below shows why String b prints null and String c prints "gg".

Correct me if I'm wrong, whenever a subclass (BClass) overrides a protected method (like initClass ()) of a superclass (AClass). If you instantiate a subclass. The superclass must use the override method specified by the subclass.

public class Example {

    public class AClass {

        private String a;

        public AClass() {
            initClass();
        }

        protected void initClass() {
            a = "randomtext";
        }
    }

    public class BClass extends AClass {

        private String b = null; 
        private String c;          


        @Override
        protected void initClass() {
            b = "omg!";
            c = "gg";
        }

        public void bValue() {
            System.out.println(b);   // prints null
            System.out.println(c);  // prints "gg"
        }
    }

    public static void main(String[] args) {
        Example.BClass b = new Example().new BClass();
        b.bValue();

    }

}

      

+3


source to share


5 answers


As JSF 12.5

In this example, you can see the order of execution. The first steps are calling constructor before constructor Object

. Subsequently, this happens:



Further, all initializers for the class instance variables [...] are executed.

Since your instance variable b is initialized to null, it will be null again

+3


source


This is because the superclass's constructor is called before the fields are initialized ClassB

. Hence, a method is called initClass()

that sets b = "omg!"

, but then again when the superclass constructor returns, is b

initialized with the value declared in ClassB

, which is null

.



To debug, put a breakpoint and step by step, you'll find yourself b

first set to null

, then changed to omg!

, and then back to null

.

+2


source


Several correct answers have already been given about what is going on. I just wanted to add that it is generally wrong to use calls to overridden methods from a constructor (except, of course, if you know exactly what you are doing). As you can see, a subclass cannot be fully initialized the moment its instance method is called (the subclass constructor logic has not yet been executed, so an efficient overridden method is called on an undefined object, which is dangerous), which can lead to confusion, such as that which is described in this question.

It is much better to write the initialization logic in the constructor, and if it is too long, split it up among several private methods called from the constructor.

+2


source


I believe this example explains the problem:

public class Main {
    private static class PrintOnCreate {
        public PrintOnCreate(String message) {
            System.out.println(message);
        }
    }

    private static class BaseClass {
        private PrintOnCreate member =
            new PrintOnCreate("BaseClass: member initialization");

        static {
            System.out.println("BaseClass: static initialization");
        }

        public BaseClass() {
            System.out.println("BaseClass: constructor");
            memberCalledFromConstructor();
        }

        public void memberCalledFromConstructor() {
            System.out.println("BaseClass: member called from constructor");
        }
    }

    private static class DerivedClass extends BaseClass {
        private PrintOnCreate member =
            new PrintOnCreate("DerivedClass: member initialization");

        static {
            System.out.println("DerivedClass: static initialization");
        }

        public DerivedClass() {
            System.out.println("DerivedClass: constructor");
        }

        @Override
        public void memberCalledFromConstructor() {
            System.out.println("DerivedClass: member called from constructor");
        }
    }


    public static void main (String[] args) {
        BaseClass obj = new DerivedClass();
    }
}

      

Exiting this program:

BaseClass: static initialization
DerivedClass: static initialization
BaseClass: member initialization
BaseClass: constructor
DerivedClass: member called from constructor
DerivedClass: member initialization
DerivedClass: constructor

      

... which demonstrates that the members of the derived class are initialized after the base class constructor (and the completion of the call to the derived class member function). It also demonstrates the key danger of calling an overridden function from a constructor , namely that the function can be called before the class members on which it depends have been initialized. For this reason, constructors should generally avoid calling member functions (and when they do, those functions must be final

either static

, so they either only depend on the current class that was initialized, or on none of the instance variables).

0


source


This is because the first AClass constructor that sets the value b = omg!

and c=gg

. After that, when BClass gets a load in memory, it sets b=null

and c stays as it is, gg, this is because since in BClass for b you do the declaration as well as initialization, and for c you only do the declaration. since c is already in memory, it won't even get a default, and since you don't initialize for c, it stays with it in an earlier state.

0


source







All Articles