Question

I would like to understand initialization of class instances in various cases..
In JLS-7 Section 12.5, there was no mention of how and when final instance variables were initialized? Can some one point me reference to understand the behaviour in case of instance variables declared as final?

   public class Test {

        public static void main(String args[]){

            Child  c1 = new Child();
        }
    }

    class Parent{
        final int a =30;
        Parent(){
            System.out.println("From super Contsrutor "+a);
            meth();
        }
        void meth(){
             System.out.println("From super");
        }
    }

    class Child extends Parent{
         final  int e=super.a;
         int b=30;
        void meth(){
            System.out.println("From Sub e=" +e+", b="+b);
        }
    }

is giving Output as following

From super Contsrutor 30
From Sub e=0,b=0

Where as

public class Test {

    public static void main(String args[]){

        Child  c1 = new Child();
    }
}

class Parent{
    final int a =30;
    Parent(){
        System.out.println("From super Contsrutor "+a);
        meth();
    }
    void meth(){
         System.out.println("From super");
    }
}

class Child extends Parent{
     final  int e=a;
    void meth(){
        System.out.println("From Sub " +e);
    }
}

is giving Output as

From super Contsrutor 30
From Sub 30
Was it helpful?

Solution

This

final int e = a;

is a constant variable, a constant expression. In the invocation

System.out.println("From Sub e=" +e+", b="+b);

the compiler can replace the use of e with its value, 30.

In

final int e = super.a;

the variable e is not a constant variable, because super.a is not a simple name, and therefore the value cannot and will not be replaced.

OTHER TIPS

first piece of Code is giving the output as below

From super Contsrutor 30
From Sub e=0,b=0

This is because of below reason.

first thing when we do new Child() , the constrcutor of Child class starts execution

but its first statement is super by default so it gives a call to parent class constrctor

now Parent class constrcutor has below code

Parent(){ System.out.println("From super Contsrutor "+a); meth(); }

so here parent class is calling meth() method and its caller is actually a subclass child's object so it calls child class meth() method.

now when it calls child class meth() method from super constrcutor actually child object is not yet created so its variables are not yet initialized but we are printing the values for both a and b.

so b gets 0 before getting assigned after child constrcutor gets execution completed.

so changing your first piece of code like below will give desired output ie putting meth() call inside child constrctor rather than on parent constrcutor.

package com.kb.finalVariables;

public class Test {

    public static void main(String args[]){

        Child  c1 = new Child();
    }
}

class Parent{
    final int a =30;
    Parent(){
        System.out.println("From super Contsrutor "+a);
       // meth();
    }
    void meth(){
         System.out.println("From super");
    }
}

class Child extends Parent{

     final  int e=super.a;
     int b=30;
     public Child() {
        meth();
    }
    void meth(){
        System.out.println("From Sub e=" +e+", b="+b);
    }
}

Lets find out the flow of the program, I have written below code for it:

package com.test;

public class Test {

    public static void main(String args[]) {
        Child c1 = new Child();
    }
}

class Parent {
    final int a = 30;
    static int count = 0;
    {
        System.out.println("Parent initialization block " + ++count);
    }
    Parent() {
        System.out.println("Parent constructor " + ++count);
        // System.out.println("From super Contsrutor " + a);
        meth();
    }
    void meth() {
        // System.out.println("From super");
        System.out.println("Parent meth method " + ++count);
    }
}

class Child extends Parent {
    final int e = super.a;
    int b = 30;
    {
        System.out.println("Child initialization block " + ++count);
    }
    public Child() {
        System.out.println("Child constructor " + ++count);
    }
    void meth() {
        System.out.println("Child meth method " + ++count);
        // System.out.println("From Sub e=" + e + ", b=" + b);
    }
}

Output:

Parent initialization block 1
Parent constructor 2
Child meth method 3
Child initialization block 4
Child constructor 5

First of all remember I have written initialization block for Parent and Child class, which is called before constructor.

Now if you can see from output on creation of Child object first Parent class is loaded into memory, then you have called meth method inside Parent constructor that will call meth method of Child class but Child but at this time initialization block and constructor of Child is not called that means at this time b is not initialized to 30 but to int default value 0, same case with e variable.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top