This question already has answers here:
What's wrong with overridable method calls in constructors?
(8 answers)
NullPointerException : Overriding constructor calling method of Base class in Derived class
(2 answers)
Closed 8 years ago.
I have a abstract class and a derived class.
Look at provided code:-
public abstract class Parent{
public Parent(){
init();
}
public abstract void init();
}
public class Child extends Parent{
private String mTitle = null;
public Child(){
super();
System.out.println(mTitle.toString());
}
public void init(){
mTitle = "It' a test";
}
}
When I will execute the above code it will throw NullPointerException on printing the value of mTitle.
If you check the code in constructor of parent I have called the the abstract method which will called the init method of derived class,
In abstract method I have initialize the value of mTitle value as ="It's a test";
After calling parent constructor derived class have to call the System.out.println.
If it is doing in that way then why it is throwing NullPointerException.
But, If I just leave the assignment of mTitle it will not throw Exception like:-
private String mTitle;
If initialization of variable occur on calling of the contruct of class and we know by default global object have initialize to null.
But in this case it will not throw Exception.
As in JLS §12.5 (Creation of New Class Instances) the following procedure is used when an instance is created:
Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.
This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.
Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.
Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.
That means your call to super() and the subsequent call to the overridden init() method are both done before the instance variable is initialized with null which discards the outcome of the init method and overwrites any value being assigned to mTitle with the null value.
This leads to the following Golden Rule: Never call non-final, non-private methods in a constructor!
According to Section 12.5 of the JLS, the superclass constructor will run before the initialiser for mTitle, which means that it will be set back to null after it is set to "It's a test".
According to section 12.5 of the JLS, the superclass constructor will run before the constructor of derived class.
The initalization of global variable is call at the time of calling of constuctor.
So when super class constructor call the abstract method and set the mTitle value in abstarct method implementation it will set the first it's value to ="it's a test".
After finishing super class constructor it will call derived class constructor and
when derived class constructor call it will first initalize its global variable which set mTitle value to the null.
As it is mention in code
private String mTitle = null;
But in second case mTitle have not assign any value in code as mention
private String mTitle;
so it will take its default value which is we assigned in implemented of abstarct method init "it a test " so it will not produce any Exception.
Related
I know that in case of Inheritance the subClass constructor should call the superClass constructor explicitly if the default constructor in the superClass is missing
but when chaining to another constructor in the subClass why we don't have to call the superClass Constructor then?
as the code below is not giving a compilation error
SuperClass:
public class Top {
public Top(String n) {
// TODO Auto-generated constructor stub
}
SubClass:
public class sub extends Top {
public sub(int x){
super("");
}
public sub(String x) {
this(5);
}
}
Because the "chained" constructor will call the superclass constructor itself. Otherwise you would be calling the superclass constructor twice (hence the effects of the parent class' constructor will execute twice which may cause an inconsistent behavior, e.g. calling instance initializers twice). More formally, the sequence of constructor calls is explained in this section of the Java Language Specification:
Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.
This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.
...
Notice that step 2 is recursive and applies to the constructor that calls the other constructor in the subclass. And step 3 applies to the constructor that calls the parent class' constructor.
if the constructors had to match exactly for all subclasses, and that subclass had to call the matching constructor, it wouldnt leave much room for change. As long as the subclass eventually calls one of the superclasses constructors, everything is fine.
This question already has an answer here:
Don’t call subclass methods from a superclass constructor
(1 answer)
Closed 7 years ago.
class superclass {
superclass() {
show();
}
void show() {
System.out.println("three");
}
}
class subclass extends superclass {
int x=3;
void show() {
System.out.println(x);
}
public static void main(String ar[]) {
subclass s=new subclass();
}
}
Output: 0
According to me: first the subclass constructor gets executed, which then calls superclass constructor. This means that, first of all, the show() method of the superclass should execute and should print three, but that is not happening. Why?
The superclass constructor is executed before any of the subclass variables are initialized. So, the x in subclass is still 0 (the default value) while the superclass constructor is executing. Polymorphism still works when a method is called in a constructor, so subclass's show is called, printing x prints 0. This illustrates the danger in calling an overridable method in a constructor -- variables may not be initialized yet. In this case, x isn't 3 [yet.
The JLS, Section 12.5, covers the steps in executing a constructor.
Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure:
Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.
This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.
Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.
Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.
(emphasis mine)
The variables are initialized after the call to the superclass constructor completes, whether that call is explicit or implicit.
subclass overrides superclass's show method. Therefore when you create an instance of subclass, subclass's show method is executed.
The reason it returns 0 and not 3 is that it is called from the constructor of superclass, which is executed before the instance variables of subclass are initialized. Therefore x still contains a default value of 0.
As i said last time you posted this question, when you make an object of subclass, it calls the superclass constructor which calls the child show() method (which overrides the super show() method) before x is initialized to 3.
If you had
subclass(){
show();
}
in your subclass, then it would print 3 because that would call the show() method after x has been initialized to that value.
If you wanted to print three then you should call super.show() in the subclass constructor.
This seems to be quite a confusing question. Per the definition, I understand that constructor is a special type of method used to initialize the state of an object and/or assign values to instance variables.
Also someone in Stack Overflow mentioned that constructor returns an object (instance) of a class, as opposed to what a normal method does/returns?
Despite going through lots of tutorials and reference materials, I couldn't find a concrete reason as to how constructor is able to return a value without the presence of a return statement.
I'm curious to find out the internal working of the entire process.
Constructors don't return anything. A constructor simply initializes an instance.
A new instance creation expression
new SomeExample();
produces a reference to a new instance of the specified class
A new class instance is explicitly created when evaluation of a class
instance creation expression (§15.9) causes a class to be
instantiated.
and invokes the corresponding constructor to initialize the created instance
Just before a reference to the newly created object is returned as the
result, the indicated constructor is processed to initialize the new
object using the following procedure:
Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then
evaluate the arguments and process that constructor invocation
recursively using these same five steps. If that constructor
invocation completes abruptly, then this procedure completes abruptly
for the same reason; otherwise, continue with step 5.
This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If
this constructor is for a class other than Object, then this
constructor will begin with an explicit or implicit invocation of a
superclass constructor (using super). Evaluate the arguments and
process that superclass constructor invocation recursively using these
same five steps. If that constructor invocation completes abruptly,
then this procedure completes abruptly for the same reason. Otherwise,
continue with step 4.
Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable
initializers to the corresponding instance variables, in the
left-to-right order in which they appear textually in the source code
for the class. If execution of any of these initializers results in an
exception, then no further initializers are processed and this
procedure completes abruptly with that same exception. Otherwise,
continue with step 5.
Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the
same reason. Otherwise, this procedure completes normally.
It gives the JVM the 'return' opcode:
'return' returns to the calling method:
http://en.wikipedia.org/wiki/Java_bytecode_instruction_listings
Code for a default constructor:
aload_0
invokespecial #1; //Method java/lang/Object
return
A Java constructor does not return anything. A constructor simply initializes a new instance of an object of a specific class. Sometimes constructors will have System.out.Println("text") which may lead you to think it returns something, but you can have that statement in any method that doesn't have a return type.
In bytecode
Test1 t1 = new Test1();
looks as follows
NEW test/Test1 //create an uninitized instance of Test1
DUP
NVOKESPECIAL test/Test1.<init> ()V // call construcctor
STORE 1 // save reference to created instance in local var
and this is constructor, void method in fact with special name <init>
public <init>()V //V means no return value, void
L0
LINENUMBER 3 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V // call super constructor
RETURN
public class SuperClass{
public SuperClass(){
System.out.println("Super class");
}
}
public class SubClass extends SuperClass{
int i;
{
i=10;
}
public SubClass(){
System.out.println("Subclass");
}
public static void main(String[] args){
SubClass sc = new SubClass();
}
}
I did a debug on all possible places and I see that first when the instance is created, it first goes to SuperClass constructor and prints Super Class and only then it comes to the instance variable and then the initialization block and then lastly SubClass constructor and prints SubClass.
But, I had read somewhere that inside the subclass constructor is where super() is called by default and that is when it goes to the superclass constructor!!!
SubClass() constructor implicitly looks like this :
public SubClass(){
super();
{
i=10;
}
System.our.println("Subclass");
}
As per the JLS section 12.5 :
Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure:
Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.
This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.
Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.
Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.
Well, that's because your SubClass constructor actually looks like this:
public SubClass() {
super();
{
i=10;
}
System.out.println("Subclass");
}
If you don't call the super(); explicitly, compiler will do it for you implicitly. That means that the SuperClass constructor is called first and THEN the `System.out.println("Subclass");
Also, the super() must be the first statement in the constructor.
You can check all of this by making the constructor of the SuperClass private (and in separate file, too). The compiler will show you an error in the SubClass constructor saying that there is no default constructor in the SuperClass.
A constructor always calls super(). That is implicit.
Read the documentation.
If a constructor does not explicitly invoke a superclass constructor,
the Java compiler automatically inserts a call to the no-argument
constructor of the superclass. If the super class does not have a
no-argument constructor, you will get a compile-time error. Object
does have such a constructor, so if Object is the only superclass,
there is no problem.
I have a class
public class MyMain{
public static void main(String... arg){
Temp t = new Temp(){
{
System.out.println(" instance initialize");
}
};
}
}
class Temp{
int i;
{
i=9;
System.out.println("Static"+i);
}
Temp(){
System.out.println("Temp const "+i);
}
}
When i execute the main method the output comes:
Static9
Temp const 9
instance initialize
Ideally, the blocks are executed before the constructor, but the inline initialization block is called after the Constructor. Why?
You're creating a subclass of Temp. For each class, any instance initializers are executed before the constructor body - but the superclass goes through initialization before the subclass initialization. So the execution flow is:
Initializers in Object
Constructor body in Object
Initializers in Temp
Constructor body in Temp
Initializers in anonymous class
Constructor body in anonymous class (none)
I would strongly advise you to refactor any code which looked like this anyway - aim for clarity rather than cleverness.
JLS 12.5 spells out the order in which things happen during construction (emphasis mine):
Just before a reference to the newly created object is returned as the
result, the indicated constructor is processed to initialize the new
object using the following procedure:
(3) This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If
this constructor is for a class other than Object, then this
constructor will begin with an explicit or implicit invocation of a
superclass constructor (using super). Evaluate the arguments and
process that superclass constructor invocation recursively using these
same five steps. If that constructor invocation completes abruptly,
then this procedure completes abruptly for the same reason. Otherwise,
continue with step 4.
(4) Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable
initializers to the corresponding instance variables, in the
left-to-right order in which they appear textually in the source code
for the class. If execution of any of these initializers results in an
exception, then no further initializers are processed and this
procedure completes abruptly with that same exception. Otherwise,
continue with step 5.
(5) Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the
same reason. Otherwise, this procedure completes normally.
To summarize, superclass constructors (step 3) are executed before instance initializers (step 4). Both are executed before "the rest of the body of this constructor" (which you don't have in your example).
The inline initialisation block is called after the constructor of the base class of the anonymous class you are instancing at the moment and before the empty implicit constructor of the anonymous class itself.
What you are actually creating is not a Temp class instance, but an instance of some anonimous class, that inherits from Temp.
Thus, at first, the Temp initializers are called (anonimous block inside Temp and its construstor) and initializers in anonimous class are called afterwards.
In your code
Temp t = new Temp(){
{
System.out.println(" instance initialize");
}
};
you are creating object of anonymous class which extends Temp class.
Creating object of Subclass:
initialize block from Superclass
constructor of Superclass
initialize block from Subclass
constructor of Subclass
Point 1: To be clear, you have two instance initializers: one in the Temp class and one in the anonymous inner class created in the main() method that is a subclass of Temp.
Point 2: Instance initializers aren't actually run before constructors. Per the JLS, they're run during a constructor, after delegating to the super constructor and before initializing instance fields and completing the constructor.
Point 3: In your code, each initializer is correctly executed at its appropriate time. I think you're expecting the second one to execute at the same time as the first one, but that would be incorrect because as pointed out in Point 1, they're initializers for two different classes.
Point 4: You may also be confused between static initializers and instance initializers. They're two distinct things.
The object must be in memory first before anything else can be done to it. The object is constructed in memory and then your console prints happen.