constructors : Java Glossary

constructors

Constructors, sometimes abbreviate to ctor by habitual text-speakers, are a special sort of method that initialise freshly minted objects. They are like static methods in that you don’t need an existing object to use them, just new. They are like instance methods in that they operate on the current object. They are a bit like static factory methods in that they are used in creating new objects, however, they don’t create objects, just initialise them. I repeat, they don’t allocate objects, they just initialise them. new allocates the space for objects.

Constructors Are Not Ordinary Methods factory
Object Initialisation Links
addNotify

Constructors Are Not Ordinary Methods

Constructors have a number of magic properties.
  1. They have the same name as the class.
  2. Constructors are not inherited. This means you have to write out reams of dummy constructors for every subclass that just invoke the corresponding super(xxx). Even if you don’t want a particular constructor, you often have to define it, just for the benefit of descendant subclasses who may need it as a base for their constructors.
  3. If you don’t define the any constructors, Java will generate a default no-argument constructor for you. You won’t actually see the code unless you examine the class file with a decompiler. If you later add some other constructor, Java will no longer continue to generate this invisible default one. You have to write it out explicitly yourself.
  4. You can’t do anything in your constructor before calling super(). If you don’t call super(xxx) or this(xxx) as the first line of code in a constructor, Java will automatically insert a call to the default no-argument superclass constructor super() for you. If the superclass has no default constructor, you will have to insert super(xxx) manually. Your call to super(xxx) must be the very first code in the constructor. You can’t even sandwich it in a try block. The only way you can wiggle around this restriction is to use methods in the parameters passed to super that have side effects.
  5. Constructors logically return an object, yet you are not allowed to declare that fact. You can’t write void either.
  6. It is possible to have ordinary static or instance methods also with the same name as the class. The compiler distinguishes these from true constructors because they have an explicit return type. Be careful!
  7. You don’t specify new inside your constructor. The space for the object has already been allocated before your constructor started to execute. All you are doing is initialising fields.
  8. You don’t return this. The constructor does not return a value. In contrast, a factory static method that created objects would return a reference to the newly minted object.
  9. If you wanted to handle your own memory management, e.g. recycle used objects, you would do this with an ordinary static method, not a constructor.
  10. Be very careful calling any methods inside your constructors. If subclasses override them, you will be invoking the subclass’s version, which may be attempting to use fields that have not been initialised yet. You won’t get a warning message! The problem usually shows up as puzzling NullPointerExceptions. The way out is to move code out of the constructor, often to the addNotify method. However, addNotify can get in analogous problem to the constructor since it too is overridden, and it may use overridden methods. One way to avoid the problem is to use only private methods in constructor initialisation.
  11. You can call a constructor only once in an object’s lifetime. Thus the constructor may initialise fields marked final where ordinary methods such as addNotify cannot, even if they are only called once in practice. A good rule of thumb is to use only final or private methods in constructors to avoid using a overridden version.

Object Initialisation

Objects are initialised in a complex series of steps. However, the process works pretty much as you expect it would have to. Constructors are just the icing on the cake in the whole scheme of object initialisation. It works like this:
  1. At compile time, all the compile time constants are effectively turned into literals. There is nothing to initialise at run time.
  2. new allocates space for an object, and zero/nulls it. The constructor code initialises it.
  3. All the fields are zeroed. It is highly convenient that 0 is the default value for int, char, null reference etc. The entire object can be bulk-zeroed with a single assembler Fill-with-zeros instruction.
  4. The constructor is started. The very first thing it does is call its superclass constructor whose job is to initialise fields in the class this one was derived from. That constructor in turn first calls its superclass constructor up the chain to Object’s constructor. The newly minted object effectively then gets initialised by a chain of constructors starting with the most basic Object. Note that no initialisation of any kind has been done of this class’s fields. If the superclasses use any methods we override, they may get a nasty surprise finding uninitialised fields.
  5. Eventually the chain of constructors returns.
  6. Fields that were initialised inline (with an = on the declare) are initialised mixed in with the fields that were initialised inside { } initialiser blocks. Assignment declare initialisation and init blocks are done in the exact order top to bottom they appear in the code. The JVM (Java Virtual Machine) does not do the assignment declare style initialisations first. If you decompile a constructor, you will see your constructors have method names like: MyClass. <init>:()V You can see them call the superclass constructor, do the instance initialisers and finally the constructor procedural code.
  7. Finally the constructor gets its chance to initialise its own fields (or modify derived ones.) with procedural code. You have to be aware of this initialisation order. Java is not smart enough to resolve initialisation dependencies. I got in trouble with this when I ran a code beautifier that put all my fields in alphabetical order. The dependencies no longer worked and the fields were initialised to the wrong values, without any warning messages.

addNotify

Don’t put GUI-type code in your constructor. Put it in an addNotify method that looks like this:

/**
 * Build the GUI
 */
public void addNotify()
   {
   super.addNotify();
   setTitle( "Whazmotron Inc." );
   ...
   }

Don’t forget to call super.addNotify() ; first, or the peer object won’t get created and your Component won’t be hooked into the actual underlying native GUI (Graphic User Interface) and you will be staring at a blank screen.

Putting GUI code here means the GUI is ready for it. The peer exists as soon at the code returns from the call to super.addNotify(), not before. the peer does not yet exist in the constructor. You need a peer for getImage type activities. Further, if you call methods in your constructor that subclasses override, it means you are less likely to be referencing variables that don’t exist yet if you divide your initialisation logically between the constructor and addNotify.

This is also a good place to move constructor code that is failing because it uses methods overridden my subclasses that reference fields not yet initialised by the subclass’s constructor which has not yet run yet.


available on the web at:

http://mindprod.com/jgloss/constructor.html
ClustrMaps is down

optional Replicator mirror
of mindprod.com
on local hard disk J:

J:\mindprod\jgloss\constructor.html
logo
Please the feedback from other visitors, or your own feedback about the site.
Contact Roedy.
Blog
IP:[65.110.21.43]
Your face IP:[23.20.34.25]
You are visitor number 95,974.