A constructor is a special method that is invoked when a new object is created. If we want to perform any one-time activities on an object at the time of its creation, then the constructor is the right place.
- Generally, the initialization of instance variables are done in the constructor.
- The purpose of a constructor is not limited to initialization. We can perform any activity in the constructor that we can do in any normal method.
- The difference is constructor is invoked automatically (implicitly) and normal method is invoked explicitly.
- Name of the constructor and its class name should be same.
- A constructor should not have a return type (void is also not allowed).
Example:
1 2 3 4 5 6 |
class Rect { Rect() { } } |
- Similar to normal methods, constructors can also take arguments.
- So constructors can be overloaded.
- The constructor that does not take any arguments is known as default constructor.
- The other constructors (that takes arguments) are known as argumented constructors or parameterized constructors.
- We can have constructors in classes and abstract classes but not in interfaces.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 |
class Rect { Rect() { } Rect(int x) { } Rect(int x, int y) { } } |
We need not to exclusively invoke the constructor, it is automatically invoked when the object is created.
Example:
1 2 3 |
Rect r=new Rect(); //default constructor is invoked Rect s=new Rect(10,20); // constructor with two ints as arguments is invoked. |
When an object is created (constructed) the instance variables of the object are automatically initialized with their default values.
If we specify (assign) any values, then the default values will be overridden. Generally, the default values are.
byte | 0 |
short | 0 |
int | 0 |
long | 0 |
float | 0.0f |
double | 0.0 |
char | ‘\0’ |
boolean | false |
Object | null |
Default Constructors In Java
The constructor that does not take any arguments is known as default constructors. This constructor is created by the system if we don’t create any constructors.
In the following program, we have created a class without any constructors. Still, a constructor is there (invisible) that is created by the system.
The system created constructor does not contain any significant code. It is just an empty block. For a class named Rect, the system created default constructor would be like
Rect()
{
}
Example Program:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class Rect { int l,b; // default constructor is not visible, but existing…as it is created by the system } class Check { public static void main(String arg[]) { Rect r1=new Rect(); //default constructor (created by the system) is invoked Rect r2=new Rect(); //default constructor (created by the system) is invoked } } |
If we want, we can define the default constructor on our own. We can feel that we are overwriting the default constructor.
When the constructor is written by the programmer (by us), some people prefer the term “no-argument constructor” instead of using “default constructor”. Whatever the name, the mechanism is the same.
- In that case, we can write any code in it. when we define the default constructor, the system does not create its version of a default constructor.
In the following example, we have created a default constructor that assigns 10 and 20 to the instance variables l and b respectively. Whenever a new Rect object is created, the code in the constructor will be executed.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
class Rect { int l,b; Rect() // default constructor created by us { l=10; b=20; } } class Check { public static void main(String arg[]) { Rect r1=new Rect(); // default constructor (created by us) is invoked Rect r2=new Rect(); // default constructor (created by us) is invoked } } |
So, a class can have only one version of default constructor whether it is created by the system or by the programmer.
Note: We cannot count how many numbers of an object created using instance variable because if variable is an instance. It will be created separately for every object creation so its initial value is if we increment it became 1.
Example: Counting objects using a static variable
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
class ConstructorCount { static int i; ConstructorCount() { System.out.println(++i); } } class Main1 { public static void main(String a[]) { ConstructorCount s=new ConstructorCount(); ConstructorCount s1=new ConstructorCount(); ConstructorCount s2=new ConstructorCount(); ConstructorCount s3=new ConstructorCount(); ConstructorCount s4=new ConstructorCount(); ConstructorCount s5=new ConstructorCount(); ConstructorCount s6=new ConstructorCount(); ConstructorCount s7=new ConstructorCount(); ConstructorCount s8=new ConstructorCount(); } } |
Output:
1 2 3 4 5 6 7 8 9 |
1 2 3 4 5 6 7 8 9 |
Argumented/Parameterized constructor:
If we want to specify some data to the constructor so that it can be used to assign/process in the constructor then we can send so like:
Rect r=new Rect(10,20);
To receive the two int values, the corresponding constructor should have 2 integer variables as formal arguments like
1 2 3 |
Rect(int x, int y) { } |
Similarly, if we want to send three values to the constructor like
Rect r=new Rect(15,25,35);
Then the corresponding constructor definition should be like
Rect(int x, int y, int z)
{
}
As constructors can be overloaded, we can have any number of constructors in a class provided their arguments differ.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
class Rect { int l,b; Rect(int x,int y) { l=x; b=y; } Rect(int x,int y,int z) { l=x+y; b=y+z; } } class Check { public static void main(String arg[]) { Rect r1=new Rect(); // INVALID as there is no suitable constructor Rect r2=new Rect(10,20); // 2-argumented constructor is invoked Rect r3=new Rect(15,25,35); // 3-argumented constructor is invoked } } |
Note: the system does not create the default constructor if we create any other constructor. In the above example, we have created 2 constructors that take some arguments.
So the default constructor is not available in Rect class. Hence the statement Rect r1=new Rect(); becomes invalid as the statement needs the default constructor.
This is why it is generally suggested to programmers to create the default constructor along with any argumented constructor. If we specifically want that the object should be created with some arguments only, then we can skip the default constructor.
When we create an object, its constructor is invoked and the code in that constructor is executed. By default, the default constructor (a constructor without arguments) is invoked when we create an object.
If we specify any arguments along with object creation, then the corresponding (argumented) constructor will be executed.
Objects as arguments to a constructor:
We can pass an object also as an argument to the constructor. A constructor of one class can take an object of the same class or other class as argument. There is no limit on no of objects passed to the constructor.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
class Square { int a; Square(int x) { a=x; } Square(Square s) { a=s.a; } } class Rect { int l,b; Rect(Rect r) { l=r.l; b=r.b; } Rect(Square s) { l=s.a; b=s.a; } } class Check { public static void main(String arg[]) { Square s1=new Square(5); // Square(int) is invoked Square s2=new Square(s1); // Square(Square) is invoked Rect r1=new Rect(s1); // Rect(Square) is invoked Rect r2=new Rect(r1); // Rect(Rect) is invoked Square s3=new Square(r1); // INVALID as there is no constructor in Square to receive a Rect object as argument. } } <br> |
Suppose we want to call both the constructors (the default constructor and the argumented constructor) with an object creation, then we call one constructor from another constructor so that both will be executed.
This mechanism of invoking more than one constructor (one constructor calling another constructor) with a single object creation is known as constructor chaining. The method this() is used to call one constructor from another constructor of the same class.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
class Rect { int l,b; Rect() { this(10,20); } Rect(int x, int y) { l=x; b=y; } } class Check { public static void main(String arg[]) { Rect r=new Rect(); // default constructor is invoked first, from there the argumented constructor is called Rect s=new Rect(25,50); // argumented constructor is directly called } } |
Private constructors
Generally, constructors are written as public so that object of the class can be created from anywhere. If we make the constructor as normal, then object of the class can be created from the current package only.
If we make the constructor as private, then other classes (even from the current package) cannot create an object of the class. This is sometimes required when we want to control the usage/creation of the object.
In that case generally, a static method is used to create the object (where the constructor is invoked from). Then the static method returns the instance/object of the class.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
class Rect { int l,b; private Rect() { System.out.println("constructor invoked"); l=20; b=35; } static Rect getRect() { System.out.println("reached static method"); return new Rect(); } void show() { System.out.println("l,b:"+l+" "+b); } } class Check { public static void main(String arg[]) { //Rect r1=new Rect(); //invalid as constructor is private System.out.println("invoking static method"); Rect r2=Rect.getRect(); System.out.println("got Rect object"); r2.show(); } } |
Output:
1 2 3 4 5 |
invoking static method reached static method constructor invoked got Rect object l,b:20 35 |
Modifiers on Constructors
the modifiers like public, protected, private, etc can be applied on constructors. But modifiers like static, final, abstract, synchronized, etc are not allowed on constructors. The following statements are not valid.
static Rect() { }
final Rect() { }
abstract Rect() { }
synchronized Rect() { }