Friday, May 21, 2004

calling final methods from constructor

"The only safe methods to call inside a constructor are those that are final in the base class "

There are cases where an instance method can be called before the constructor.  This gives odd results.  For example the following code:

public class SpecialFish extends Fish{
 public String species = "Walleye";
 void printSpecies(){
 System.out.println("the species is: "+species);
 } 
public static void main(String[] args) {
 SpecialFish sf = new SpecialFish();
 sf.printSpecies();
 } 
} 
class Fish {
 String defaultSpecies = "Carp";
 public Fish() {
 printSpecies();
 } 
 void printSpecies(){
   System.out.println("This is the species: "+defaultSpecies);
 } 
} 

You might expect the above to print "Carp" and then "Walleye",  but it prints "null" and then "Walleye"

The reason for this is that by default, Java waits until run-time to decide what object it is working on. 

Making a method final is the way to ensure that it is bound at compile time instead of run time.  Final is telling java that this method cannot be overridden.

Without making the printSpecies() method final, java has no clue if Fish or Special Fish will be using it, so it waits until run-time and then prepares (constructs) the base class so that it is ready to morph into any class, base or derived, that it might need to be.  In other words, it executes in the following order:

  1. the base-class constructors are called
  2. member initializers are called in the order of declaration
  3. the body of the derived class is called

So, the base-class constructor is called and inside that constructor you have a call to the printSpecies method.  Being a SpecialFish, the overridden printSpecies method gets called before the SpecialFish is even a twinkle in it's daddy's eye.  It's like asking a kid to take the SAT seconds before he is conceived.

So, the rule is, don't call a method that could be overriden from inside the constructor.


11:41:34 PM    comment []