I am facing a problem with the below program , it has two classes A and B and one method getObject() in Class A that has been overridden in class B, Class B extends Class A.
I am calling getObject() from the base class constructor which I believe it will call the overridden method in class B, and at runtime the error is null pointer exception, why the Object has not been initialized, even so it has?
class A {
Object object = new Object();
public A() {
System.out.println("A Class");
getObject();
}
public void getObject() {
System.out.println("Class A Version");
System.out.println(object.toString());
}
}
class B extends A {
Object object = new Object();
public B() {
System.out.println("B Class");
}
#Override
public void getObject() {
System.out.println("Class B Version");
System.out.println(object.toString());
}
}
public class Init {
public static void main(String[] args) {
new B();
}
}
output
A Class
Exception in thread "main" Class B Version
java.lang.NullPointerException
at net.mindview.util.B.getObject(Init.java:28)
at net.mindview.util.A.<init>(Init.java:8)
at net.mindview.util.B.<init>(Init.java:21)
at net.mindview.util.Init.main(Init.java:34)
According to this answer:
The correct order of initialisation is:
Static variable initialisers and static initialisation blocks, in textual order, if the class hasn't been previously initialised.
The super() call in the constructor, whether explicit or implicit.
Instance variable initialisers and instance initialisation blocks, in textual order.
Remaining body of constructor after super().
See sections §2.17.5-6 of the Java Virtual Machine Specification.
So basically, object in class B is not initialized yet during constructor of class A is being executed (point 2: implicit super() call).
Within B constructor you call A construct which is using B's getObject() which is using not initialized object from B.
Use debugger step by step and you will see the flow.
The NPE is coming from the class itself, not object. While the constructor is working, this is null.
B extends A, so there's an implicit super constructor call inserted. That prints your "A Class" line, but then the method call is equivalent to this.getObject();, and this is null.
I think the key point of this problem is that you should know that the constructor of super class (A in case) will be called first. let's assume antoher condition that A also extends C , in case, constructor of c will be called first.
so the order of call should be : 1 construtor of C, 2 constructor A and then constructor of B at the last.
For your case, because Constructor A was called first , at this point object is not initialized yet which cause the null pointer excetion
Execution orders are:
class A {
Object object = new Object(); // --------------- 2
public A() {
System.out.println("A Class"); // ---------- 3
getObject(); // ---------------------------- 4 (calls B.getObject())
}
public void getObject() {
System.out.println("Class A Version");
System.out.println(object.toString());
}
}
class B extends A {
Object object = new Object(); // --------------- 7 (not executed)
public B() {
System.out.println("B Class"); // ---------- 8 (not executed)
}
#Override
public void getObject() {
System.out.println("Class B Version"); // -- 5
System.out.println(object.toString()); // -- 6 (exception!)
}
}
public class Init {
public static void main(String[] args) {
new B(); // ------------------------------- 1
}
}
You should never call overridable method in constructors as it introduces ambiguity in terms of which method to call. In you case your super class A calls B's getObject(). At this Point B is yet not instantiated so the call fails and gives you NPE.
Related
This question already has answers here:
Are fields initialized before constructor code is run in Java?
(5 answers)
Closed 2 years ago.
I'm trying to understand why the output of the following Java code is as like this:
class A {
public A() {
System.out.print("A()");
}
public static void main(String[] args) {
}
}
class B {
public B() {
System.out.print("B()");
}
public static void main(String[] args) {}
}
class C extends A {
B b = new B();
}
public class E05SimpleInheritance {
public static void main(String args[]) {
new C();
}
}
Output:
"A()B()"
I would imagine that when the main method of the E05SimpleInheritance public class is called the following things should happen
Non-public class C is loaded and its fields are initialized(before calling the default constructor of class C)
Since its member 'b' is an object of class B, class B is loaded in memory
Since we construct an object of Class B its constructor is called which should print B()
Default constructor of C is called which automatically calls the constructor of the superclass A which print A()
So the final output should be B()A() which is obviously wrong so I do not really understand how the code flows in this case. Can you perhaps show me why is A()B() printed instead of B()A()
Your mistake is in step 1:
Non-public class C is loaded and its fields are initialized(before calling the default constructor of class C)
This is not what’s happening. In reality, non-static fields are initialised at the beginning of the constructor, not before it. And the base class constructor is implicitly (or explicitly) invoked even before that.
In other words, javac generates code for C which is equivalent to the following:
class C extends A {
B b;
C() {
super();
b = new B();
}
}
This question already has answers here:
Java order of Initialization and Instantiation
(2 answers)
Closed 3 years ago.
Exactly when the Class members are initialized ?
In below code:
public class A{
public B b = new B();
private C c = new C(123);
public A (arg a){
// Do something
}
public someMethod(){
Log.i(TAG, " "+ b.getD());
}
}
main(){
A a = new A ("xyz"); }
When would be the Object of Class B & C created? And is it guaranteed to be created?
Should a professional app use such code or not ?
You can analyze the question this way:
class Scratch {
public static void main(String[] args) {
A a = new A ("xyz");
}
}
class A{
public B b = new B();
private C c = new C(123);
public A (String a){
System.out.println("new A()");
}
}
class B {
public B() {
System.out.println("new B()");
}
}
class C {
public C(int i) {
System.out.println("new C()");
}
}
which executes giving the following output:
new B()
new C()
new A()
which matches wiith the answer of #Jakir Hossain.
So: inline fields initializers are executed before code in constructor, following the same order which they are declared in.
Instances of classes B and C are created on A's instance creation, before A's constructor is executed. This ordering (and fields' initialization) are guaranteed.
When an object is created, the following things are done in the following order:
The object is allocated on the heap with the correct object type,
and all instance fields are "default initialized" to zero, false or
null.
The expressions in the super(...) or this(...) are evaluated and the
constructor for the next class up the chain is called. (This
recurses up the chain constructor, so that the Object constructor
gets executed first.)
The instance variable initializers and any instance initializer
blocks are executed in order.
The body of the constructor is executed.
The constructor returns.
Hope it helps you.
class A {
public A() {
System.out.println("Constructor A");
}
}
class B extends A {
public B() {
System.out.println("Constructor B");
}
}
class C extends B {
public C() {
System.out.println("Constructor C");
}
public static void main(String[] args) {
C c = new C();
}
}
When running the code then it calls all constructor but needs to call only child constructor.
output like only print
Constructor C
Like the comments and the other answer already said, this is explicitly impossible.
If a class (class Foo) extends another class (class Bar), then all constructors of Foo must directly or indirectly call one of the constructors of Bar. This is done either through explicit invocation or implicit invocation.
class Foo {
// No constructor is specified, so a default, empty constructor is generated:
// Foo() { }
}
class Bar extends Foo {
Bar() {
// Explicit call to a constructor of the super class is omitted, so a
// default one (to Foo()) is generated:
// super();
}
}
In the Java Language Specification § 12.5 it is written how new instances are created. For any class other than Object the super constructor is always executed.
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.
So a super constructor is always called. If you want to print only "Constructor C", then you need to do any of the following:
Change the constructor of B so it no longer prints "Constructor B" by either removing the println statement or removing the no-argument constructor alltogether.
Add a second constructor within B which does not print anything and call it from C:
B(boolean b) {
}
C() {
super(true);
}
Make sure C does not extend B anymore:
class C {
public C() {
System.out.println("Constructor C");
}
}
No, you can't do this. Java will call all constructors according the hierarchy.
I wrote down this mini-program:
A class:
public class A
{
public A()
{
System.out.println(getS());
}
public String getS() { return s;}
}
B class:
public class B extends A
{
private String s = "hello2";
public String getS() { return s;}
}
main:
public static void main(String[] args)
{
B b = new B();
}
and it printed:
null
Why is that?
I know that the String that printed is B's string, but why it didn't initialized before?
According to this answer - the variable initialized before the constructor..
EDIT -
I edited the code so the unrelated code won't confuse
Here is what's going on: when you construct B, the first thing its constructor needs to do is constructing A. This is done before B's own field s is initialized.
A constructs its own s, and then calls getS. However, it does not get its own getS, because B provides an override for it. Recall that B.s has not been initialized yet. That is why you see null printed.
Follow-up reading: What's wrong with overridable method calls in constructors?
What is happening:
You create a B instance, this will call the super() so the constructor of A.
Here it will do the print using the getter getS(). This will use the getter of B since this is the type of this but in this getter, the String is not yet instanciate since it is still doing the super class construction, so it return null.
Note that the String s in A is hidden by the one in B
The order during an instance is :
the static (from the super then the class)
the super class declaration (statement then constructor)
the block statement
the constructor
As Seen with :
public class A{
static{System.out.println("sA");}
{System.out.println("A1");}
public Main() {
System.out.println("new A");
}
{System.out.println("A2");}
public static void main(String[] args) {
new A();
}
}
class B extends Main {
static{System.out.println("sB");}
{ System.out.println("B1"); }
public B() {
System.out.println("new B");
}
{ System.out.println("B2"); }
}
Output :
sA
sB
A1
A2
new A
B1
B2
new B
it prints null because you have polymorphism in java. You Overrided method getS(). So when you call it from A, you try to call getS() from class B. But you didn't create instance of class B yet, because you need to finish class A first. So String in class B haven't been initialized yet, because of it you get null.
Consider the following code classes.
public class A
{
public A()
{
callCreation();
}
protected void callCreation()
{
System.out.println("A Created!!");
}
}
public class B extends A
{
protected void callCreation()
{
System.out.println("B Created!!");
}
}
public class C extends B
{
protected void callCreation()
{
System.out.println("C Created!!");
}
public static void main(String[] args)
{
A a = new A();
A b = new B();
A c = new C();
}
}
The output of running the class C is given below.
A Created!!
B Created!!
C Created!!
The first output line in the output A Created!! is printed because when the constructor of class A is called, it calls the super class's constructor (java.lang.Object) implicitly before calling the callCreation() method in the class A's constructor. And this will be the case for B and C classes too. In that case when the constructor of B is called the call flow should be typically : B's constructor -> A's Constructor -> java.lang.Object's Constructor -> come back to A's callCreation() method to finish calling A's constructor. If so how is the overridden value printed and not the super class's value is printed? So the question is 'when is an object of a class created exactly? to put it in other words, the object of a class should be created only after the constructor finishes calling/initializing all the elements within itself. If so how can a method be called from a child class and not from the parent class?
The callCreation methods in B and C override the method from A. So when the method is called in the constructor A the implementations in B and C will be run, even though the constructors of B and C have not been executed yet. This is possible because constructors don't actually create the object, rather they are called to initialize some moments after the JVM has created it.
In general it's a very bad idea to call methods that can be overridden from a constructor for this very reason. A method in B or C may assume that the constructor and object initializers have already been run, and read an unexpected value from a field. For example the following ends up printing "B Created!! null" because the field still has not be assigned its value.
public class B extends A
{
final String msg = "Yes!";
protected void callCreation()
{
System.out.println("B Created!! "+msg);
}
}
thinking in this way makes it more obvious:
when an object of type B is being created super() keyword calls the A constructor,
then in A constructor "this.callCreation()" is executed, which refers to the current
object which is B, so callCreation corresponding to the current object(B) is called.
the same process is done for C.
public class A {
public A() {
this.callCreation();
}
protected void callCreation() {
System.out.println("A Created!!");
}
}
class B extends A {
public B() {
super();
}
protected void callCreation() {
System.out.println("B Created!!");
}
}
class C extends B {
public C() {
super();
}
protected void callCreation() {
System.out.println("C Created!!");
}
public static void main(String[] args) {
A a = new A();
A b = new B();
A c = new C();
}
}