0% found this document useful (0 votes)
10 views15 pages

Understanding Constructor Chaining in Java

The document explains constructor chaining in Java, detailing how constructors can invoke other constructors within the same class or from parent classes. It provides examples that illustrate the importance of default constructors and the use of 'this()' for calling the same class's constructor. Additionally, it discusses various scenarios involving method overriding and the implications of static and instance variables in class constructors.

Uploaded by

swoobhai
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views15 pages

Understanding Constructor Chaining in Java

The document explains constructor chaining in Java, detailing how constructors can invoke other constructors within the same class or from parent classes. It provides examples that illustrate the importance of default constructors and the use of 'this()' for calling the same class's constructor. Additionally, it discusses various scenarios involving method overriding and the implications of static and instance variables in class constructors.

Uploaded by

swoobhai
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd

How Does Constructor Chaining Work?

When you invoke a constructor from another constructor,


it's called constructor chaining. Whether you're dealing with
a standalone constructor or a parent class' constructor, the
end of the chain will always be the Object's class constructor
because every class is inherited from the Object class by
default.
So lets' look at the below scenario to understand it better:
class Parent {
public void Parent() {
[Link]("inside parent without arguments");
}
public Parent(int a) {
[Link]("inside parent with argument");
}
}
class Child extends Parent {
public void Child() {
[Link]("inside child without arguments");
}
public Child(int b) {
[Link]("inside child with argument");
}
public static void main(String[] args) {
Child child = new Child();
Child child1 = new Child(15);
}
}

So what should the output be? It will give a compilation


error.
1. Line 18 will give a compilation error saying that there is
no default constructor in the Parent class. Huh?
Doesn't the compiler add a default constructor by itself? No.
Let's understand what the compiler is trying to do here:
 The compiler doesn't add a default constructor (no
args) if you have already defined a constructor with
arguments.
 The compiler tries to add a super() call as the first call
in the constructor if you don't add it yourself.
2. Line 23 will give compiler error because there is no
default constructor defined in Child.
So how can we fix it?
1. We can fix line 18 in the following two ways:
 Add a super(b), super call with an argument to the
Parent class in the constructor of the Child class.
 Add a default constructor in the Parent class.
2. We can fix line 23 by adding a default constructor in the
Child class:
class Parent {
// this is method not a constructor
public void Parent() {
[Link]("inside parent without arguments");
}
// this is default constructor.
public Parent() {
super(); // hidden call to Object's default constructor
[Link]("inside parent's default constructor");
}
public Parent(int a) {
super(); // hidden call to Object's default constructor
[Link]("inside parent's argument constructor");
}
}
class Child extends Parent {
// this is a method
public void Child() {
[Link]("inside child without arguments");
}
// this is a default constructor
public Child() {
super(); // hidden call to Parent's default constructor
[Link]("inside child's default constructor");
}
public Child(int b) {
super(b); // Case - 1 : call to Parent's argument constructor
[Link]("inside child's argument constructor");
}
public static void main(String[] args) {
Child child = new Child();
Child child1 = new Child(15);
}
}

Output :
inside parents's default constructor
inside child's default constructor
inside parent's argument constructor
inside child's argument constructor

What Is this() Used For?


If you need to call the same class' constructor, then you can
use this() as the first statement of the constructor. It can be
with or without arguments based on which constructor you
want to invoke.
class Child extends Parent {
// this is a method
public void Child() {
[Link]("inside child without arguments");
}
// this is a default constructor
public Child() {
this(); //can we call this here?
[Link]("inside child's default constructor");
}
public Child(int b) {
this(); // invoke default constructor of Child class
[Link]("inside child's argument constructor");
}
public static void main(String[] args) {
Child child = new Child(15);
}
}

Output:
Line 9, will give a compilation error. It is a recursive call to
the default constructor. However, it is legitimate to call it on
line 14 because it is being called from an argument
constructor. If we remove line 9, then the output will be :

inside parent's default constructor


(the compiler will add a call to super() in the default constructor of the
Child class, which will invoke Parent's default constructor)
inside child's default constructor
inside child's argument constructor
What happens when you try to compile and run the following
program?
public class MySuper
{
String str1 = "x";
public MySuper()
{
myMethod();
}
void myMethod()
{
[Link](str1);
}
}
public class MySub extends MySuper
{
String str2 = "y";
void myMethod()
{
[Link](str2);
}
public static void main(String[] args)
{
MySub mySub = new MySub();
}
}

Select the correct answer:


 A: This code writes "x" to the standard output.
 B: This code writes "y" to the standard output.
 C: This code writes "xy" to the standard output.
 D: This code writes "yx" to the standard output.
 E: This code writes "null" to the standard output.
Ans:

1. By creating the object of MySub, the constructor of the


superclass MySuper is called.
2. The constructor of MySuper invokes the method
myMethod.
3. The method myMethod is overridden in the subclass
MySub.
4. The method myMethod writes the value of str2 to the
standard output.
5. The constructor of the superclass tries to access the
variable str2 inside its subclass before it is initialized.
Therefore the program writes null instead of "y" to the
standard output.
What is written to the standard output as the result of
executing the following code?
public class MyClass {
static int x;
String s = "";
static String s2 = "";
public MyClass(int i) {
x += i;
s += x;
s2 += x;
}
public static void main(String[] args) {
new MyClass(2);
MyClass mc = new MyClass(1);
new MyClass(4);
[Link](mc.s + mc.s2);
}
}

Select the correct answer.


 A. This code writes "1137" to the standard output.
 B. This code writes "3237" to the standard output.
 C. This code writes "35" to the standard output.
 D. This code writes "312" to the standard output.
 E. This code writes "323" to the standard output.
Ans:

1. By creating the first object and passing the argument 2


to the constructor, the statement x += i; increments
the value of x by 2. The statement s += x; adds the
string value of 2 to object s. The statement s2 += x;
adds the string value of 2 to static string s2.
2. By creating the second object, we pass the value 1 to
the constructor. The statement x += i; increments the
value of x by 1. Therefore, x = 3. Remember that x is a
static variable. The statement s += x; adds the string
value of 3 to object s. String s is not static.
Therefore, the value of s of the object mc is equal to
3. The statement s2 += x; adds the string value of 3 to
the static object s2. String s2 is static. That is why
there is only one copy available for all the objects of the
class MyClass. The first value of the object s2 was the
string value of 2 (see the first step). The string value of
3 is also added to s2.
3. By creating the third object, string s wouldn't be
affected because its value is of object mc — and that is
3. The statement x += 4; increments the value of the
static variable x by 4. The last value of x was 3. So, x =
3 + 4 = 7. The static string s2 would write 237, and
that value is the same for all the objects of MyClass.
The correct answer is b.
What is written to the standard output as the result of
executing the following code?
public class MyException {
int[] accounts = new int[13];
int nr;
public void print(int i, int i2) {
try {
nr = accounts[i] / i2;
[Link]("R");
}
catch (ArithmeticException ae) {
[Link]("S");
}
catch (Exception e) {
[Link]("T");
}
}
public static void main(String[] args) {
MyException me = new MyException();
[Link](13, 2);
[Link](12, 0);
}
}

 A. This program writes "SS" to the standard output.


 B. This program writes "TT" to the standard output.
 C. This program writes "ST" to the standard output.
 D. This program writes "TS" to the standard output.
 E. This program writes "RS" to the standard output.
 F. This program writes "SR" to the standard output.

Ans:
1. By passing the parameters 13 and 0 to the method
print, the statement nr = accounts[i] / i2; causes an
ArrayIndexOutOfBoundsException. The reason is that
element 13 doesn't exist. The equation nr =
accounts[i] / i2; first tries to access element 13, then
divides the number by zero. The code doesn't handle
ArrayIndexOutOfBoundsExceptions, but the Exception
is a generic Exception handler. The statement
[Link]("T"); writes T to the standard output.
2. By passing the parameters 12 and 0 to the method
print, the statement nr = accounts[i] / i2; divides zero
by zero, which causes an ArithmeticException. The
statement [Link]("S"); writes S to the
standard output. The correct answer is: D.
What happens when the following program is compiled and
run?
public class MyClass {
int y = 3;
public MyClass(int i) {
y += i;
}
public MyClass(int i, int i2) {
y += (i + i2);
[Link](y);
}
public int method(int i) {
y += i;
return y;
}
public static void main(String[] args) {
new MyClass(new MyClass(5).method(2), 4);
}
}

 A. This program writes "12" to the standard output.


 B. This program writes "24" to the standard output.
 C. This program writes "21" to the standard output.
 D. This program writes "17" to the standard output.
 E. This program writes "18" to the standard output.
 F. This program writes "16" to the standard output.

Ans:
1. The statement new MyClass(5).method(2) creates a
new object by passing the one-argument constructor of
the class MyClass.
2. By passing 5 to the constructor, the statement y += i;
increments the value of y by 5. So y = 3 + 5 = 8.
3. By invoking the method and passing the value 2 to it,
the statement y+= i; increments the value of y by 2. So,
y = 8 + 2 = 10.
4. The statement new MyClass(new
MyClass(5).method(2), 4); creates a new object by
calling the two-argument constructor.
5. The method returns the value 10. So, the statement
new MyClass(new MyClass(5).method(2), 4); is
equivalent to new MyClass(10, 4);
6. The y += (i + i2); increments the value of y by 10 + 4 =
3 + 10 + 4 = 17.
The correct answer is: d.
If the following code is compiled and run, it writes nothing
to the standard output.
Write only one statement at line 29. The statement should
apply the following.
1. The statement creates the object mc from the class
MyClass.
2. The statement should assign the value y to the object
str, assign the value 9 to the variable i, and the value 8
to the variable i2.
3. As a result of adding the statement, the output of the
code should become y98.
What is that statement?
public class MyClass
{
static String str = "x";
static int i = 2;
static int i2;

MyClass(String str, int i, int i2)


{
MyClass.i2 = i2;
if(![Link]("") || i != 0 || i2 != 3)
{
[Link](i2);
}
}
String strMethod(String str)
{
[Link] = str;
[Link](str);
return str;
}
int intMethod(int i)
{
MyClass.i = i;
[Link](i);
return i;
}
public static void main(String[] args)
{
// add your statement here!
}
}

Ans:
1. We actually need to invoke the method intMethod to
assign a value to the variable i and invoke the
strMethod to assign a value to the object str.
2. By instantiating the class MyClass, we can create an
object. At the same time, we assign a value to the
variable i2.
3. By creating objects, the statement [Link](i2);
writes the value of i2 to the standard output. That is
unwanted in some cases. Therefore, we invoke the
methods as follows:
MyClass mc = new MyClass(new MyClass("", 0, 3).strMethod("y"), new
MyClass("", 0, 3).intMethod(9), 8);

4. By adding the previous statement at line 29, the output


of the program becomes y98.
What happens when the following program is compiled and
run?
public class MyClass {
String str = "";
String str2 = "";
MyClass() {
this("z");
[Link](str + str2);
}
MyClass(String str) {
this("x", "y");
[Link] += str;
[Link]([Link] + str2);
}
MyClass(String str, String str2) {
[Link] += str;
this.str2 += str2;
[Link]([Link] + this.str2);
}
public static void main(String[] args) {
MyClass mc = new MyClass();
}
}

 A. This program writes "xyzyy" to the standard output.


 B. This program writes "xyz" to the standard output.
 C. This program writes "xyxzy" to the standard output.
 D. This program writes "xyxzyxzy" to the standard
output.
 E. This program writes "zxy" to the standard output.
 F. This program writes nothing to the standard output.

Ans:

Common questions

Powered by AI

In nested class hierarchies, constructors are invoked from the highest superclass down to the current class. Default constructors use super(), invoking the parent class's default constructor first. Parameterized constructors can use custom super(argument) to specify which parent constructor to invoke. This interaction is critical, as it dictates the initialization order of the object's state. In mismatched or undefined sequences, compilation errors occur, emphasizing the need for precise declaration and invocation of required constructors .

Static variables are shared among all instances of a class, whereas non-static variables (instance variables) are specific to each object. When an object is created, each instance receives a copy of non-static variables but not of static variables. In the given program, static variable x accumulates changes across object instantiations, while non-static variable s only reflects changes within a single object. This leads to the output "3237" as x (static) affects s2, the static string combined value across objects .

Default constructors play a crucial role in object-oriented programming by providing a no-argument constructor if none is explicitly defined. This becomes particularly important in class hierarchies where a subclass constructor implicitly calls its superclass constructor. In cases where a superclass only defines constructors with arguments, a default constructor must be explicitly defined to allow subclass instantiation. The absence of such a default constructor results in a compilation error, as observed in the relationship between Parent and Child classes .

An unexpected 'null' output occurs due to method overriding and object initialization order. When a constructor in a superclass calls an overridden method that accesses subclass fields, those fields are not yet initialized. In the provided example, the MySuper constructor calls myMethod, overridden in MySub. Since str2 of MySub is uninitialized when myMethod is invoked, 'null' is printed instead of the expected value .

Overloaded constructors allow object creation with different sets of initial values, affecting the initialization process. Each constructor can set different initial states, leading to varied object behavior. In the MyClass example, invoking different constructors results in distinct initializations of y, affecting subsequent operations. The sequence of calls and aggregates from overloaded constructors determines the final state of object variables, producing specific outputs such as '17', depending on which constructor is triggered first .

The order of method invocation and object creation directly impacts program output. Constructors are executed immediately during object creation, often initializing values or invoking methods. In chained constructor calls, especially with 'this()' or 'super()', initialization order is crucial. The program output depends on the order and combination of constructor and method calls, which can define variable states and affect subsequent logic, as demonstrated where specific variable initializations lead to output variations like "12" .

To correct a recursive constructor call, you should ensure that 'this()' is not being invoked in a way that calls the same constructor repeatedly. Instead, adjust the constructor logic to invoke a different constructor or ensure that 'super()' is called if initialization from a superclass is required. Removing or restructuring the invocation lines, such as removing a self-referential 'this()' could prevent the recursion and enable successful program execution, as seen by correcting calls inside the Child class constructors .

Exception handling in nested try-catch blocks processes exceptions starting from the innermost block outward. Each catch block must handle specific exceptions; unhandled exceptions propagate outward. In the specified code, an ArrayIndexOutOfBoundsException and ArithmeticException are handled by specific catch blocks. The ArrayIndexOutOfBoundsException is caught by the generic Exception block, printing 'T', while the ArithmeticException is caught by a specific ArithmeticException handler, printing 'S'. As a result, the output is "TS" .

The use of 'this()' within a constructor calls another constructor of the same class. It affects control flow by re-routing execution to a different constructor. However, care must be taken to avoid recursive calls (i.e., a constructor calling itself), which leads to compile-time errors. For instance, in the provided code, a compilation error occurs when 'this()' is used to call the same constructor recursively within the default constructor of the Child class .

Constructor chaining is significant as it ensures that a sequence of constructors is called, starting from the base class's constructor down to the derived class's constructor. This is vital in object-oriented programming because it guarantees that all the necessary initializations across classes in the hierarchy are completed correctly. In the given example, without proper constructor chaining (through the use of super()), a compilation error occurs due to the lack of a default constructor in the Parent class, blocking the instantiation of the Child object .

You might also like