I want to call only child class constructor in multilevel inheritance? - java

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.

Related

Why the value of Object is null, even it has been initialized?

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.

Why can't this be done?

class A {
A(int x) { System.out.println("constructor A"); } }
class B extends A {
B() { System.out.println(" constructor B"); } }
public class C {
public static void main(String args[]) { B b = new B(); } }
It says constructor from class A can't be applied for given types.
You have to call the constructor A(int x) explicitly in your constructor B(). I.e., you have to write
class B extends A {
B() {
super(<<< insert some int here>>>);
System.out.println(" constructor B");
}
}
If you do not add such a super call, then java will insert super(); for you which would try to call A(). As there is no constructor A() you receive the error that your constructor cannot be applied for the argument types.
Its always good to have a default constructor in a class if your writing a paramterized one.
class A {
A(){System.out.println("Default A");}
A(int x) { System.out.println("constructor A"); } }
class B extends A {
B() { System.out.println(" constructor B"); } }
public class C {
public static void main(String args[]) { B b = new B(); } }
If we don't specify a constructor to a class A, then a default constructor with no args will be associated to the class, if you specify one/more constructor to the class A, then you have to use one of them each time you want to create an object from this class.when a class B extend a class A, then constructors have to call one constructor of the parent class ( A ) by super() , if you don't specify a constructor to A then it's implecitly called be the constructor of B, if you explecitly defined constructor of A , then You have to call it when you create constructor of B like this :
B() { super(0)/*this call should be if the first line, you have to pass your default args if the constructor have args*/;
System.out.println(" constructor B");
}
what you are seeing is constructor chaining, read
snippet from the link.
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.

When should the constructor of the superclass be called from the subclass?

The statement that calls the constructor of the superclass should be the last statement in the constructor of a subclass.
Is it a valid statement?
No, It should be the first statement of the sub class.
Invocation of a superclass constructor must be the first line in the
subclass constructor.
Check here for more details
No,that is not a valid statement.It MUST be the first statement of the child class's constructor.
If you don't add that line,the compiler will automatically add it.
Example:
class A {
public A() {
System.out.println("Inside A's constructor.");
}
}
class B extends A {
public B() {
// super(); // THIS LINE WILL BE AUTOMATICALLY ADDED BY THE COMPILER.
System.out.println("Inside B's constructor.");
// super(); // THIS LINE WON'T COMPILE.
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
}
}
No it should be first statement...
Even though if the default constructor is absent in the first line of sub class constructor, the compiler implicitly calls the default constructor of its super class

Using the extended class constructor

I was wondering if it was possible to do the following with a Class, that extends another class in Java, if so. How?:
public class HelloWorld {
public HelloWorld() {
A aClass = new A(22);
}
}
public class A extends B {
public A() {
System.out.println(number);
}
}
public class B {
public int number;
public B(int number) {
this.number = number;
}
}
Your A constructor needs to chain to a B constructor using super. At the moment the only constructor in B takes an int parameters, so you need to specify one, e.g.
public A(int x) {
super(x); // Calls the B(number) constructor
System.out.println(number);
}
Note that I've added the x parameter into A, because of the way you're calling it in HelloWorld. You don't have to have the same parameters though. For example:
public A() {
super(10);
System.out.println(number); // Will print 10
}
Then call it with:
A a = new A();
Every subclass constructor either chains to another constructor within the same class (using this) or to a constructor in the superclass (using super or implicitly) as the first statement in the constructor body. If the chaining is implicit, it's always equivalent to specifying super();, i.e. invoking a parameterless superclass constructor.
See section 8.8.7 of the JLS for more details.

What is the wrong with this java code?

I am learning java. The book I'm reading has a question which asks what is wrong with the following code? I have typed the code in NetBeans and I can see the error but why is this error caused and how is it resolved?
The error is highlighted over the code public A(int t) and it says
Constructor B in class B cannot be applied to given types, require int, found no arguments, reason actual and formal arguments lists differ in length.
Here is the code:
public class Test {
public static void main(String[] args) {
B b = new B(5);
}
}
class A extends B {
public A(int t) {
System.out.println("A's constructor is invoked");
}
}
class B {
public B(int k) {
System.out.println("B's constructor is invoked");
}
}
when your super class has an args constructor and doesn't have a no-args constructor you have to explicitly invoke it using a super(args) call from sub-class constructor
class A extends B {
public A(int t) {
super(t);
System.out.println("A's constructor is invoked");
}
}
Class B has defined constructor, so it does not have public implicit default constructor (with no arguments). All subclass constructors have to explicitly call superclass constructors, via super(t), if zero argument superclass constructor is not available.
The class B has only one constructor which takes an int argument. On the other hand, the constructor you have in class A (implicitly) tries to call a constructor in A's super class (namely B) that takes no arguments. This is the cause of the error. There are at least two ways to fix the problem:
Create a no-arg constructor in class B.
Explicitly call the constructor in class B which takes an int as a parameter. You can do this using the super keyword.
You need to call the constructor of the super class as the first statement in A(int):
public A(int t) {
super(t);
System.out.println("A's constructor is invoked");
}

Categories