Wednesday, December 18, 2013

Constructor, constructor chaining and overloading of constructor in Java

Everybody knows what a constructor is i.e, constructor create new object but the purpose of this post is cover detailed concepts about constructor which includes rules for creating and defining constructors, constructor chaining and what is the need of private constructor and when does compiler provide the default constructor for us. 

Objects are constructed. You can't make a new object without invoking a constructor.
In fact, you can't make a new object without invoking not just the constructor of the object's actual class type, but also the constructor of each of its superclasses.

Constructors are special methods that create and return an object of the class in which they’re defined. Constructors have the same name as the name of the class in which they’re defined, and they don’t specify a return type—not even void

3 Steps of object declaration, creation and assignment.
  • Step 1. Declare a reference variable
    • Latte mylatte = new Latte();
    • Make a new reference variable of a class or interface type
  • Step 2. Create an object
    • Latte mylatte = new Latte();
  • Step 3. Link the object and the refernce
    • Latte mylatte new Latte();
    • Assign the new object to the reference.

Q. Are we here calling a method name Latte()? Because it sure look like it.
No We're calling the Latte constructor.
A constructor does look and feel a lot like a method, but it is not a method. It's got the code the run when you say new.  The only way to invoke a constructor is with the new keyword.


Constructor Basics
Every class, including abstract classes, MUST have a constructor. Store this into your brain. It is not necessarily to type it just because class must have one.

A Constructor look like:
 class latte {  
  latte(){ }       
 }  

Have you noticed something is missing? There is no return type!

Two point to remember about constructors:
  • they have no return type 
  • their names must exactly match the class name

Typically, constructors are used to initialize instance variable state, for instance
 class latte {  
  int size;  
  String name;  
  latte(int size, String name){  
  this.size=size;  
  this.name=name;  
  }       
 }

Here you may be noticed that latte class doesn't have no-arg constructor. That means the following will fail to compile:

latte l = new latte(); // won't compile

but the following will compile

latte l = new latte(5,"caffee"); // no problem, argument match the latte constructor

What we get from this, is that it's very common and may be desirable for a class to have a no-arg constructor, regardless of how many other overloaded constructor is present in the class.
Oh, yes, constructor can be overloaded.


How Constructor Chaining works



Consider the basic animal hierarchy where we assume Horse extends Animal and Animal extends Object.

 class Animal{  
 }  
 Class Horse extends Animal{  
 }  


We know that constructors are invoked at runtime when you say new on some class type as follows:
Horse h = new Horse();

  1. Horse constructor is invoked. Every constructor invokes the constructor of its superclass with an (implicit) call to super(), unless the constructor invokes an overloaded constructor of the same class.
  2. Animal constructor is invoked because Animal is the superclass of Horse.
  3. Object constructor is invoked.At this point we're on the top of the stack.
  4. Object instance variables are given their explicit values. By explicit values, we mean values that are assigned at the time the variables are declared.
  5. like "int x = 5", where "5" is the explicit value (as opposed to the default value) of the instance variable.
  6. Object constructor completes.
  7. Animal instance variables are given their explicit values.
  8. Animal constructor completes.
  9. Horse instance variables are given their explicit values (if any)
  10. Horse constructor completes.

Summary













The MUST remember rules for constructor to answer any interview questions regarding constructor

  1. Constructors can use any access modifier, including private.
    A private constructor means only code within the class itself can instantiate an object of that type, so if the private constructor class wants to allow an instance of the class to be used, the class must provide a static method or variable that allows access to an instance created from within the class. Click here to see more
  2. The constructor name must match the name of the class.
  3. Constructors must not have a return type.
  4. It's legal (but stupid) to have a method with the same name as the class, but that doesn't make it a constructor. If you see a return type, it's a method rather than a constructor.
  5. If you don't type a constructor into your class code, a default constructor will be automatically generated by the compiler. we will see this in the next section
  6. The default constructor is ALWAYS a no-arg constructor.
  7. If you want a no-arg constructor and you've typed any other constructor(s) into your class code, the compiler won't provide the no-arg constructor for you.
  8. Every constructor has, as its first statement, either a call to an overloaded constructor (this()) or a call to the superclass constructor (super()), although remember that this call can be inserted by the compiler.
  9. If you do type in a constructor and you do not type in the call to super() or a call to this(), the compiler will insert a no-arg call to super() for you, as the very first statement in the constructor.
  10. A call to super() can be either a no-arg call or can include arguments passed to the super constructor.
  11. You cannot make a call to an instance method, or access an instance variable, until after the super constructor runs.
  12. Only static variables and methods can be accessed as part of the call to super() or this().
  13. Abstract classes have constructors, and those constructors are always called when a concrete subclass is instantiated.
  14. The only way a constructor can be invoked is from within another constructor. In other words, you can't write code that actually calls a constructor. You try by yourself to check this.

Whether a Default Constructor Will Be Created
The following example shows a Horse class with two constructors:
class latte{  
      latte(){ }  
      latte(String name){ }  
 }  
In this case compiler won't put default constructor.
class latte{  
      latte(String name){ }  
 } 
In this case also compiler won't put default constructor.
 class latte{ } 
In this case compiler will generate a  default constructor for the preceding class, because the class doesn't have any constructors defined

what about this class?
class latte{  
      void latte(){ }  
 } 
It might look like the compiler won't create one, since there already is a constructor in the latte class.What's wrong with the latte() constructor? It isn't a constructor at all! It's simply a method that happens to have the same name as the class.



Overloaded constructor

Overloading a constructor means typing in multiple versions of the constructor, each having a different argument list, like the following examples:
 class Latte{  
      Latte(){  
      }  
      Latte(String name){  
      }  
      Latte(int size){  
      }  
      Latte(String name, int size){  
      }  
      Latte(int size,String name){  
      }  
 }
If you have 2 constructor that took only an int, for example, the class wouldn't compile. What you name the parameter variable doesn't matter. It's the variable type and order that matters. A constructor that takes a string followed by an int, is not the same as one that takes an int followed by string.
Overloading a constructor is typically used to provide alternate ways for clients to instantiate objects of your class. For example, if a client knows the animal name, they can pass that to an Animal constructor that takes a string. But if they don't know the name, the client can call the no-arg constructor and that constructor can supply a default name.

Five different constructor means five different ways to make a new Latte object.


Example
 public class JavaLatte {  
      String name;  
      JavaLatte(){  
           this("Cafee Latte");  
      }  
      JavaLatte(String name){  
           this.name=name;  
      }  
      public static void main(String javalatte[]){  
           JavaLatte jv = new JavaLatte();  
           System.out.println(jv.name);  
           JavaLatte jv1 = new JavaLatte("Cappicino");  
           System.out.println(jv1.name);  
      }       
 }

The key point to get from this code example. Rather than calling super(), we're calling this(), and this() always means a call to another constructor in the same class. OK, fine, but what happens after the call to this()? Sooner or later the super() constructor gets called, right? Yes indeed. A call to this() just means you're delaying the inevitable. Some constructor, somewhere, must make the call to super().


The benefit of having one constructor invoke another overloaded constructor is to avoid code duplication.
The call to super() must be the first statement in each constructor.For instance, following code won't compile.
 class Latte{  
      Latte(){  
      }  
 }  
 class JavaLatte extends Latte{  
      int size;  
      JavaLatte(){  
           size=5;  
           super();  
      }  
 }  

Superclass constructor with arguments
If superclass constructor has arguments? Can you pass something in to the super() call?
Of course. If you couldn't, you had never be able to extend a class that didn't have a no-arg constructor.
Imagine a scenario :
All animal have a name. There is getName() method in class Animal that returns the value of the name instance variable. The instance variable is marked private, but the subclass inherits getName() method. So here is the problem Horse has a getName() method, but does not have the name instance variable.
Horse has to depend on the Animal part of himself to keep the name instance variable and return it when someone call getName() on a Horse object
Question is how Animal part get the name???
The only reference Horse has to the animal part of himself is through super(), so this is the place where Horse send the name to the Animal object.
abstract class Animal{  
      private String name;  
      public String getName(){  
           return name;  
      }  
      public Animal(String name){  
           this.name=name;  
      }  
 }  
 class Horse extends Animal{  
      Horse(String name){  
           super(name);  
      }  
 }  
 public class HorseDemo{  
      public static void main(String[] javalatte){  
           Horse h = new Horse("HORSE ONE");  
           System.out.println(h.getName());  
      }  
 }  

Overridden constructor?
One last point on the whole default constructor thing, constructors are never inherited. They aren't methods. They can't be overridden (because they aren't methods and only instance methods can be overridden). So the type of constructor(s) your superclass has in no way determines the type of default constructor you'll get. Some folks mistakenly believe that the default constructor somehow matches the super constructor, either by the arguments the default constructor will have (remember, the default constructor is always a no-arg), or by the arguments used in the compiler-supplied call to super(). So, although constructors can't be overridden, you've already seen that they can be overloaded, and typically are.




Q1Doesn't the compiler always make a no-arg constructor for you?
Ans:
No. The compiler gets involved with the constructor making only if you don't say anything at all about constructor. If you write a constructor that takes arguments, and you still want a no-arg constructor, you'll have to build the no-arg constructor yourself.

Q2Do constructor need to be public?
Ans: No. Constructor can be public, private or default
Puzzle Question:
class latte{   
      String name;   
      latte(){   
           return;   
      }   
      latte(String name){   
           this.name=name;   
           return;   
      }   
 }   
 public class javalatte{   
      public static void main(String javalatte[]){   
           latte l = new latte("java.latte");   
           System.out.println(l.name);   
      }   
 }   
Guess the output?




If you know anyone who has started learning java, why not help them out! Just share this post with them. Thanks for studying today!...

3 comments: