Home of The JavaSpecialists' Newsletter

094Java Field Initialisation

Posted: 2004-09-20Category: LanguageJava Version: 1.5+Dr. Heinz M. Kabutz
 

Abstract: 

 

Welcome to the 94th edition of The Java(tm) Specialists' Newsletter. I would like to welcome Nelson Boegbah from Liberia onto our list (we now have readers from 101 ). Can you imagine a city of one million residents, without any running water, electricity or telephone lines? I certainly cannot imagine that, but that is what Monrovia (capital of Liberia and Nelson's home) is like. Nelson has promised to write a few stories about life in Liberia. They are off-topic for our Java newsletter, so if you are interested, please send me an email, and we can start a Life-In-Liberia newsletter :-)

August 2004 was extremely busy. I spent my days and nights developing a J2ME application for a customer. It reminded me of my PhD days - working until 3:00am every morning (I'm sure you can relate to that ;-). The highlight was one Friday night, when I sneaked into bed at 1:00am, and felt guilty because there were still two productive hours left in the day! As you may imagine, there was not too much time left over to write newsletters, but I AM BACK!

This newsletter was written based on an idea sent to me by Remco de Boer from the Netherlands.

Attention: On the 30th of November 2004, I would have been sending The Java(tm) Specialists' Newsletter for exactly four years. I want to try publish the 100th newsletter on that same day. If you have good ideas that you would like to share with 8000+ Java specialists in 101 countries, please email them to me. I want to thank all those who have helped grow this newsletter over the past 4 years by forwarding it to their friends and colleagues :-)

Birthday and Anniversary Special: Since the 30th November 2017 is the 17th anniversary of our newsletter and my birthday is coming up on the 4th December, we are giving away a 30% discount on our new Data Structures for Java 9 Course (Late 2017 Edition). Whether you are a seasoned Java programmer or you just want to get ready for your next job interview, this course will help you. Besides detailed lectures, the course has over 130 questions that will help you discover what you missed.

Java Field Initialisation

The idea is to have two classes, an abstract superclass and a subclass implementation. The subclass' constructor calls the superclass constructor, which in its turn calls an abstract method implemented by the subclass. The method implementation sets a (subclass) member variable - and this is where the fun begins.

I have often seen code like this:

public class MyClass {
  private boolean b = true; // unnecessary initialisation
  private int i = 42;       // unnecessary initialisation

  public MyClass(boolean b, int i) {
    this.b = b;
    this.i = i;
  }
}
  

The writer of MyClass was being overcautious, by initialising fields that are actually being set in the constructor anyway. "Oh, but it does no harm." Really? Before we look at Remco's example, let us decompile the class and see what the compiler did with the field initialisers:

public class MyClass {
  public MyClass(boolean flag, int j) {
    b = true;
    i = 42;
    b = flag;
    i = j;
  }

  private boolean b;
  private int i;
}
  

If we look carefully, we see that the field initialisers get copied into the constructor as part of compilation. The steps "b = true" and "i = 42" are thus of no use at all. I find this interesting. All the initialising code and the initialiser blocks, are copied into each of the constructors.

Another quick example:

public class MyClass2 {
  { System.out.println("Goodbye"); }

  public MyClass2() { }
  public MyClass2(boolean b) { }
  public MyClass2(boolean b, String s) { }

  private int i = 4;

  { System.out.println("Hello"); }
}
  

becomes the compiled class:

public class MyClass2 {
    public MyClass2() {
        System.out.println("Goodbye");
        i = 4;
        System.out.println("Hello");
    }

    public MyClass2(boolean flag) {
        System.out.println("Goodbye");
        i = 4;
        System.out.println("Hello");
    }

    public MyClass2(boolean flag, String s) {
        System.out.println("Goodbye");
        i = 4;
        System.out.println("Hello");
    }

    private int i;
}

Now, let us look at the classes that Remco sent me:

public abstract class A {
  public A(int i) {
    build(i);
  }
  protected abstract void build(int i);
}
  

and its subclass

public class B extends A {
  private int size = 0;
  public B(int size) {
    super(size);
  }
  protected void build(int size) {
    this.size = size;
  }
  public int size() {
    return size;
  }
  public static void main(String[] args) {
    B test = new B(1);
    System.out.println("Size: " + test.size());
  }
}
  

The resultant output is:

Size: 0
  

Correct, but it is easy to think that the output should rather be "Size: 1", but it is "Size: 0"! You can prevent this by not explicitly setting the B.size field to 0 in the declaration. In other words, declaring private int size; provides the expected answer ('Size: 1').

According to the JVM Language Specification, this is expected behaviour. A superclass is initialized before the member variables of a subclass. Explicitly setting the member variable to 0 therefore takes place after the super constructor called the build method (note that you can set the size to anything you want, not necessarily 0). When you leave out the explicit '= 0', the variable is of course still (implicitly) initialized to 0. However, this implicit default initialization ('preparation') is performed before the superclass constructor. [See for instance section 2.17.6, in particular steps 3 and 4].

It makes sense, when we consider that the initialisation code (size=1) is moved to the start of each constructor.

final: The confusion could have been avoided by changing the design of the application. I usually try to make all fields final. This would have highlighted the problem in the code from the start.

Kind regards

Heinz

 

Related Articles

Browse the Newsletter Archive

About the Author

demo

Java Champion, author of the Javaspecialists Newsletter, conference speaking regular... About Heinz

Java Training

We deliver relevant courses, by top Java developers to produce more resourceful and efficient programmers within their organisations.

Java Consulting

Nobody ever wants to call a Java performance consultant, but with first-hand experience repairing and improving commercial Java applications - JavaSpecialists are a good place to start...

Threading Emergency?

If your system is down, we will review it for 15 minutes and give you our findings for just 1 € without any obligation.