I am an AP Java Student and I am practicing for my exam. I came across this question and I don't understand the answer:
Consider the following classes:
public class A
{
public A() { methodOne(); }
public void methodOne() { System.out.print("A"); }
}
public class B extends A
{
public B() { System.out.print("*"); }
public void methodOne() { System.out.print("B"); }
}
What is the output when the following code is executed:
A obj = new B();
The correct answer is B*. Can someone please explain to me the sequence of method calls?
The B constructor is called. The first implicit instruction of the B constructor is super() (call the default constructor of super class). So A's constructor is called. A's constructor calls super(), which invokes the java.lang.Object constructor, which doesn't print anything. Then methodOne() is called. Since the object is of type B, the B's version of methodOne is called, and B is printed. Then the B constructor continues executing, and * is printed.
It must be noted that calling an overridable method from a constructor (like A's constructor does) is very bad practice: it calls a method on an object which is not constructed yet.
The base class must be constructed before the derived class.
First A() is called which calls methodOne() which prints B.
Next, B() is called which prints *.
Related
public class A {
public A() {
System.out.println("A");
}
}
public class B extends A{
public B() {
System.out.println("B");
}
}
public static void main(String[] args){
B b1 = new B();
Output:
A
B
So what's confusing me is, the Inheritance documentation of Java states that:
Constructors are not members, so they are not inherited by subclasses,
but the constructor of the superclass can be invoked from the
subclass.
From my understanding of that, unless you specifically call for super() in the constructor of class B, it should not print A.
So the question is, why does it print A?
The compiler calls the default constructor (no-arg constructor) of the superclass initially from the subclass constructor. So you don't need to explicitly call it. That's why the line is getting printed above.
If you want to call non-default constructor (constructor with arguments) of superclass, then you would have to explicitly call it form subclass.
In the below code , I have three questions. I know that having same function in both Parent and Child class does not make any sense and not at all a good design. But , since Java is allowing me to do this , it was possible to write the below code. Trying to understand what actually happens under the hood.
1.When I call f() from the constructor of class A I found that it is calling the child class f(). This is an expected behaviour. But , when the parent constructor calls the overloaded f() before initialising the child class members ,why “B” is getting printed.
2.Why I have two values for a final variable X (x=null , x=B)?.
class A{
A(){
System.out.println("A's Constructor");
f();
}
void f() {System.out.println("A");}
}
class B extends A{
B(){
System.out.println("B's Constructor");
f();
}
final String x = "B";
void f() {System.out.println(x);}
}
public class JavaPOCSamples {
public static void main(String[] args) {
// TODO Auto-generated method stub
//System.out.println("Java POC");
new B();
}
}
Output as below when “B”.trim() is used in the above code:
A's Constructor
null // Note that a final variable X is null
B's Constructor
B // Note that a final variable X is changed to "B"
It is exactly the expected behaviour and is exactly why you should never call overridable methods from a constructor.
The constructor of B first calls the constructor of A, that calls f(), (from class B because it's overridden), that prints x, which is still null. Then B sets it's initialized member variables (so x is no longer null), prints something and calls f() again...
That's is because of the Java Language Specification of Inheritance. Here is a quote from Oracle Java docs.
With super(), the superclass no-argument constructor is called. With super(parameter list), the superclass constructor with a matching parameter list is called.
Note: 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.
Small & Simple Explanation:
super() means the constructor (equivalent) of immediate parent class.
class A{
A(){
System.out.println("A's Constructor");
f();
}
// overloaded constructor
// calling super(int a) in child class will call this
A(int a){
System.out.println("A's Constructor " + a);
f();
}
void f() {System.out.println("A");}
}
Specs means, in an inheritance, when an object of the Child Class is created/instantiated, the Object of the Parent Class must instantiate first. So by default super() is invoked always even if you don't invoke it explicitly (any of the overloaded super(arg...) method) in your code.
If you call an overloaded super(args...) of your parent class from your child class, then the default super() is not called.
That means, in your code, Java Compiler puts the default line of super() at very first line in the child constructor, when you don't invoke any of super constructors.
Practical Proof ?? (in your code..??)
class A{
A(){
System.out.println("A's Constructor");
f();
}
// overloaded constructor
// calling super(int a) in child class will call this
A(int a){
System.out.println("A's Constructor " + a);
f();
}
void f() {System.out.println("A");}
}
class B extends A{
B(){
// super(); java adds this line when you don't put any super(args...) call
System.out.println("B's Constructor");
f();
}
B(int a){
super(a);
System.out.println("B's Constructor "+ a);
f();
}
final String x = "B".trim();
void f() {System.out.println(x);}
}
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
//System.out.println("Java POC");
new B(5);
}
}
Output: (Read comments for some hints..)
A's Constructor 5
null
B's Constructor 5
B
try to play with super() calls.. and get more questions to learn Java deeper. :)
Cheers!!
Recommended reads...
https://stackoverflow.com/a/3767389/6446770
https://stackoverflow.com/a/3767391/6446770
https://stackoverflow.com/a/3767421/6446770
class A {
A() {
System.out.print("A");
}
}
class B extends A {
B() {
System.out.print("B");
}
}
class C extends B {
C() {
System.out.print("C");
}
}
public class My extends C {
My(){
super();
}
public static void main(String[] args) {
My m = new My();
}
}
Question starts from one Interview Question (what happens when an object is created in Java?)
and answer is...
The constructor for the most derived class is invoked. The first
thing a constructor does is call the consctructor for its
superclasses. This process continues until the constrcutor for
java.lang.Object is called, as java.lang.Object is the base class for
all objects in java. Before the body of the constructor is executed,
all instance variable initializers and initialization blocks are
executed. Then the body of the constructor is executed. Thus, the
constructor for the base class completes first and constructor for the
most derived class completes last.
So, according to above statement, answer should be ABCC, but it showing only ABC. Although, when i'm commenting the super() in derived constructor. Then, output is ABC. Please, help me to figure out, did i misunderstand the above paragraph. ?
No, the answer is ABC
My m = new My();
The above first invokes My class, then a super call is made to its super class i.e., C class, then a super call to B class is made, then a super call to A Class, then a Super call to java.lang.Object as all objects extend java.lang.Object.
Thus the answer is ABC.
You don't really need to explicitly call super() in your My class as it'd be included by the compiler unless you call an overloaded constructor of that class like this(something).
The below code will print ABC
To invoke the constructor of the super class, the compiler will implicitly call the super() in each and every class extending the class, if you are not calling the super construcotr explicitly.
abstract class A {
public void methodA() {
System.out.println("methodA");
methodB();
showName();
}
public abstract void methodB();
public void showName() {
System.out.println("in showname base");
}
}
class B extends A {
public void methodB() {
System.out.println("methodB");
}
public void showName() {
System.out.println("in showname child");
}
}
public class SampleClass {
public static void main(String[] args) {
A a = new B();
a.methodA();
}
}
Output is :
methodA
methodB
in showname child
Question :-
Since in overriding, the object type is considered. Is it the reason behind that class B's showName() method called not of class A's? If not then whats the cause of this output order?
You created an object of type B, so all methods called on that object will be on class B. If class B does not implement some methods (like methodA), then Java tries to find a method in the parent class (A). You should read about polymorphism in object oriented languages:
http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming
It's easy:
A a = new B();
a.methodA();
here is known that a is object of B class, so every method that can be overriden in class B is used from class B if there is no overriding, then method from class A must be used.
Considering order:
you invoke methodA that is declared as:
public void methodA() {
System.out.println("methodA");
methodB();
showName();
}
from inside of methodA() you invoke both methodB() and showName(). They are overriden in class B, and object a is instanceof B, so that's why they (from B class) are used.
EDIT as mentioned in comment:
#Jaikrat Singh, class B is still class A (child of it, but inheritance is relation of type: IS-A ). Class B has inherited methods from A class. So it has methodA as well. So it's better to say, that methodA is also called from class B but with is default code - the same as provided in class A
While the object 'a' is declared as type A, it is instantiated as type B. Polymorphism causes the methods of the instance type to be called rather than those of the declaration type, so because it is internally of type B, the showName() method of class B is called.
When you call a.methodA(), since your object type is B, it will look for methodA first in B. Since there is no such method in B, it will look for this method in its super class, which is A. Finding methodA in class A, it will start to execute.
Executing, it will print methodA and start looking for the next called method (methodB), which is implemented in the B class, then it will print methodB.
The next called method is showName, which is implemented in both classes. Since Java will start looking for the implementation in the same class as the object type, it will find in its first attempt, which is class B.
The main rule is simple: Java will first try to find the method in the object type class (the name that goes after the new operator). If the method is not implemented there, it will start to go up through the super classes.
You have the abstract class A, and it is extended by B. Extends is equivalent to B "is a" A. For example if apple extended fruit, apple 'is a' fruit. It acts like a fruit but also does apple things that a banana wouldn't do. So B acts the same way as A, but then also can do other stuff. So in your example, your B overwrites two methods. They will be called by every B object by default. In order to access A's methods from a B, you need to use the keyword super .
It is part of polymorphism (a key point in java programming) that an object will find any methods in itself first (even if they are overwritten from a parent) and then it will climb the tree of inheritance to find a method that isn't directly in that class.
For your example:
public void methodA() {
System.out.println("methodA"); //This prints no problem.
methodB(); //This searches the "B" class for a method called "methodB" If it can't find it, it checks its parent for a "methodB"
showName();//This searches the "B" class for a method called "showName" If it can't find it, it checks its parent for a "showName"
}
The above code gets called. You know this much (from other comments you made, I'm assuming this.) Once the line methodB() gets called, your object of type B checks the entire B file for the method. It would only jump up to A for the method if it didn't exist. Then it would do the same for showName().
public class A {
public A() {
System.out.println("a1");
}
public A(int x) {
System.out.println("a2");
}}
public class B extends A {
public B() {
super(5);
System.out.println("b1");
}
public B(int x) {
this();
System.out.println("b2");
}
public B(int x, int y) {
super(x);
System.out.println("b3");
}}
I don't understand why the default constructure of A is not applied when I run B b= new B();
B extends A, so First we call the constrcture of A that supposed to print "a1", and then we call the the second constructure of A which prints "a2" and B() prints "b1", but when I run it, it prints only "a2,b1", so obviously A() wan't applied at the beginning- why?
When you say B b = new B(); you are calling the default constructor which is
public B() {
super(5);
System.out.println("b1");
}
Since this already has a call to its super constructor [super(5)] so the compiler will not insert the implicit default constructor. Hence the result.
NOTE: From your question, it seems that you have the idea that all the constructors are called when you create an object. I am afraid that is incorrect. Only that constructor will be called which you explicitly call to create the object. And if that constructor calls other constructor via the this() method, only then the other constructors will be called.
B extends A, so First we call the constrcture of A that supposed to print "a1"
This statement is incorrect.
In class B your no arguments constructor
public B() {
super(5);
System.out.println("b1");
}
calls the constructor of the superclass (class A) which takes an int parameter.
public A(int x) {
System.out.println("a2");
}
You never make a call to super() so the constructor that prints "a1" will not be called when you call any of B's constructors
Calling a super constructor must be the first line of a constructor. If you wish to call the no argument constructor of a superclass (in this case, the one that prints "a1"), you would write...
public B() {
super();
System.out.println("b1");
}
If you do not specify calling a super constructor, then java will automatically put in a call to the no argument super constructor.
That's because you call super(5) in B constructor which call the second A constructor instead of the first one.
I think you missunderstand how Java handles constructors. First of all, by default Java will call only one constructor per class, unless you explicitly tell it to call more using this(...). Secondly, that one construct that is called is the default constructor of the super class (so it will call super(), not this()); so class A actually looks like this:
public class A {
public A() {
super(); // implicit call to super(), which is Object()
System.out.println("a1");
}
public A(int x) {
super(); // implicit call to super(), which is Object()
System.out.println("a2");
}
}
So invoking A() will implicitly call Object(), however invoking A(int x) will also implicitly call Object(), and not - how you seem to assume - A().
Since in B you always explicitly specify to call another constructor, the compiler will not add anything. Below I added comments on what will happen on the calls to super(...) and this(...)
public class B extends A {
public B() {
super(5); // explicit call to A(5), no implict call to A()
System.out.println("b1");
}
public B(int x) {
this(); // explicit call to B(), no implicit call to A()
System.out.println("b2");
}
public B(int x, int y) {
super(x); // explict call to A(x), no implicit call to A()
System.out.println("b3");
}
}
So again, the important thing to remember is that Java will insert a call to super() in the first line of any constructor, unless you explicitly invoke another constructor using this(...) or super(...). It will never insert this() by itself.