Java Interview Questions

Java Interview Questions


Java interview questions and answers focused on "Method overriding and Method hiding".
There are interview questions on other topics like Multithreading, Exception Handling, Type Casting, Ambiguous Overloaded methods etc with detailed explanation on each question.

You will get link of all articles at bottom of this post.


Question 1:  
Can we Override static methods in java? What is method hiding in Java? What is the output of below program?
 
class Parent{ 
 public static void print(){ 
  System.out.println("I am Parent"); 
 } 
}

class Child extends Parent{ 
 public static void print(){ 
  System.out.println("I am Child"); 
 } 
}

public class MainClass { 
 public static void main(String args[]) { 
  Parent parent = new Parent(); 
  parent.print(); 
  
  parent = new Child(); 
  parent.print(); 
  
  Child child = new Child(); 
  child.print(); 
 } 
}
Output : 
I am Parent 
I am Parent 
I am Child

Explanation: No. Static methods cannot be overridden.

Static methods are not polymorphic and doesn't take part in run time or dynamic polymorphism and the decision as to which method will be called is resolved at compile time based on the type alone.

We can declare static methods with same signature in subclass, but it is not considered as overriding because there won’t be any run-time or dynamic polymorphism.
If a derived class defines a static method with same signature as a static method in base class, the method in the derived class hides the method in the base class.

 
even if caller writes like,  
Parent parent = new Parent();  
parent.print(); 

Compiler at compile time will change above line to Parent.print() because static methods need to be called in static way and is not associated to any instance.


Parent parent = new Child();  
parent.print();

Above line would have printed "I am Child" if static methods are polymorphic.
So internally what it does is, Compiler checks whether print() method is static, if yes, then it replace the instance to instance type.
parent object is of type Parent, so it replaces it to,
Parent.print();

Question 2: 
Can a Static method be called using instance variable? What if that instance variable is null, will it throw Null pointer exception? 
For class (or static) methods, the type of reference on which the method is invoked is important or object being referred is important?
Static method call is evaluated at compile time or run-time?

What is the output of below program?

class Parent{ 
 public static void print(){ 
  System.out.println("I am Parent"); 
 } 
}

public class MainClass { 
 public static void main(String args[]) { 
  Parent parent = null; 
  parent.print();
 } 
}

Output :
I am Parent 

Explanation:
Parent parent = null;
parent.print();

So internally what Compiler does is it checks whether print() method is static, if yes, then it replace the instance to instance type.
parent object is of type Parent, so it replaces it to, Parent.print(); at compile time itself and at runtime there is no Null Pointer Exception.


Question 3: 
What do you mean by instance method of Subclass cannot override static method of Base class?
What is the output of below program?
 
class Parent{ 
 public static void print(){ 
  System.out.println("I am Parent"); 
 } 
}

class Child extends Parent{ 
 public void print(){ 
  System.out.println("I am Child"); 
 } 
}

public class MainClass { 
 public static void main(String args[]) { 
  Parent parent = new Child(); 
  parent.print(); 
 } 
}

Output :
Compilation Error at line 8
Error says: "This instance method cannot override the static method from Parent"

Explanation:

An instance method from subclass cannot override static(class) method from super class.

Lets say Java allows instance method overriding static method from parent class, then "parent.print();" will call print() method of Parent or Child class?

print() method is static in Parent class, so call should be evaluated to Parent.print() but at the same time print() method in subclass is not static and it supports polymorphic behavior. so what to do?

that is why it gives compile error and doesn't supports instance method overriding static methods from Super class. 

Question 4: 
What do you mean by static method of Subclass cannot hide instance method of Base class?
What is the output of below program?
 
class Parent{ 
 public void print(){ 
  System.out.println("I am Parent"); 
 } 
}

class Child extends Parent{ 
 public static void print(){ 
  System.out.println("I am Child"); 
 } 
}

public class MainClass { 
 public static void main(String args[]) { 
  Parent parent = new Child(); 
  parent.print(); 
 } 
}

Output :
Compilation Error at line 8
Error says: "This static method cannot hide the instance method from Parent"

Explanation:
An static method from subclass cannot hide instance method from super class.

Lets say Java allows static method hiding instance method from parent class, then "parent.print();" will call print() method of Parent or Child class?

print() method is not static in Parent class, it will check whether Subclass has provided overridden version of print(), yes it has, so it should call print() of Child class, but print method of child class is static and
and call can be resolved to both child and parent class print() method, now which method to invoke? so to remove this ambiguity java doesn't allows static method from subclass hiding instance method from super class..

that is why it gives compile error and doesn't supports static method hiding instance methods from Super class. 



Question 5: 
Methods exhibits polymorphic behavior in case of dynamic polymorphism? What about variables?
Are variables polymorphic? Variables are resolved at compile time or run time?
What is the output of below program?
 
class Parent{ 
 public int var = 10;
 
 public void print(){ 
  int var = 20;
   
  System.out.println("I am Parent 1:"+var);
  System.out.println("I am Parent 2:"+this.var);
 }
}

class Child extends Parent{ 
 public int var = 30;
 
 public void print(){ 
  int var = 40;
   
  System.out.println("I am Child 1:"+var);
  System.out.println("I am Child 2:"+this.var);
  System.out.println("I am Child 3:"+super.var);
 } 
}

public class MainClass {

 public static void main(String[] args) {
  Parent p = new Parent();
  System.out.println(p.var);
  p.print();
  System.out.println("---------------");
  
  Child c = new Child();
  System.out.println(c.var);
  c.print();
  System.out.println("---------------");
  
  Parent pc = new Child(); //(OR p = c)
  System.out.println(pc.var);
  pc.print();
  System.out.println("---------------");
 }
}

Output :
10
I am Parent 1:20
I am Parent 2:10
---------------
30
I am Child 1:40
I am Child 2:30
I am Child 3:10
---------------
10
I am Child 1:40
I am Child 2:30
I am Child 3:10
---------------


Explanation:
Variables doesn't exhibit polymorphic behavior but exhibits inheritance
Subclass will have access to both variables, one from parent and one of its own.

If you declare a variable of the same name in subclass, that's called hiding. 
You can access the one from the superclass with super.var or ((SuperClass)this).var.
The variables don't even have to be of the same type; they are just two variables sharing a same name, much like two overloaded methods.

The scope of field being accessed(super class field or subclass field) will be determined at compile time by the type of the class that the field is being referenced from.
Example:
Superclass sc = new Subclass()
System.out.println(sc.var);
The compile time type of sc is Superclass, so var of superclass is binded at compile time.

This is resolved at compile time and not at run time.
Resolving anything at compile time doesn't exhibit polymorphic behavior.


If the variable "var" is made static at both parent class and in subclass or at either class, it will be perfectly valid and there would be no change in output.



Question 6: 
If variable is bind at Compile time then what is the output of below program?

public class MainClass {
 public static void main(String[] args) {
  Parent p = new Child();
  System.out.println(p.getObject().x);
 }
}

class Parent {
 int x = 10;

 public Parent getObject() {
  return new Parent();
 }
} 

class Child extends Parent {
 int x = 20;

 public Child getObject() {
  return new Child();
 }
}

Output :
10

Explanation:
Variables doesn't exhibit polymorphic behavior but exhibits inheritance.

p.getObject().x

In this case, Compiler checks the type of "p" which is "Parent" and at compile time it just checks whether Parent class has "getObject()" method or not. 

If not then it throws "The method getObject() is undefined for the type Parent"
If yes then it just check the return type of getObject() method because ultimately "x" is going to be invoked on that reference and in our case it is Parent, 

So p.getObject().x will be evaluated to Parent.x at compile time logically.

If you change the return type of getObject method in Parent class to Child then output will be 20.


Question 7: 
What is the output of below program?

public class MainClass {

 public static void main(String[] args) {
  Parent p = new Child();
  p.print();
 }
}

class Parent {
 public static int x = 10;

 public void print() {
  System.out.println(x);
 }
} 

class Child extends Parent {
 public Child() {
  x = 30;
 }
}

Output :
30

Explanation:

Child class is not hiding the x variable(hiding happens when it declares the variable with same name) but it simply changes the value of static variable that it has received from Parent class.




Question 7: 
What are the different ways by which main method can be written?

public class MainClass {
  public synchronized final static void main(final String[] args) {
   //code
  }
}

Explanation:
Writing main method in the way shown above is perfectly valid. 
You can also remove "synchronized final" and "final" in argument and still the call is perfectly valid.


Question 8: 
What do you mean by Method hiding, are static methods inherited to subclass, explain with example?
public class MainClass {
 public static void main(String[] args){
  Parent.print();
  Child.print();
 }
}

class Parent {
    public static void print() {
        System.out.println("I am Parent");
    }
}

class Child extends Parent {
   
}


Output:
I am Parent
I am Parent

Explanation:
Static methods including instance methods(public, protected and default) are inherited to subclass.

Only difference is, if subclass defines method with same name and signature that is present in super class then there is difference in the way static method and instance method will work.

STATIC METHODS:

If subclass defines method with same name & signature as one present in Superclass then for STATIC METHODS it is said to be method hiding and not method overriding.

It is said to be method hiding because there will be no polymorphic behavior achieved.

Lets understand with example,
public class MainClass {
 public static void main(String[] args){
  Parent parent = new Child();
  parent.print();
  
  Child child = new Child();
  child.print();
 }
}

class Parent {
    public static void print() {
        System.out.println("I am Parent");
    }
}

class Child extends Parent {
    public static void print() {
        System.out.println("I am Child");
    }   
}


Output of above program is 
I am Parent
I am Child

because no polymorphism is achieved and instance type that is,
for line parent.print(); instance type is Parent and print() method of Parent  class will be invoked.
for line child.print(); instance type is Child and print() method of Child class will be invoked.

Note: If it exhibits polymorphism then output will be "I am Child" for line parent.print().

METHOD HIDING

Child class also provides implementation of print method. so child.print(); method invokes print() method of Child class and not Parent class because Child class has hide the super class print() method by providing implementation of it and that is why it is called Method hiding.


INSTANCE METHODS:
 
If subclass defines method with same name & signature as one present in Superclass then for INSTANCE METHODS it is said to be method overriding and not method hiding.
It is said to be method overriding because there will be polymorphic effect.

If we run the same above program by removing static to print() method and making it instance method then output will be .
I am Child.
I am Child.

output of line parent.print(); is "I am Child" because it checks whether Parent class has print() method and yes it has then it checks whether Subclass has provided his own implementation of print method, Yes, so print() method of Child class is invoked.


Question 9: 
How Deserialization works in Java? How are constructors called during serialization and deserialization? Deserialization process invokes constructor for creating object?

class Parent implements Serializable{
 public Parent(){
  System.out.println("Parent Constructor");
 }
}

class Child extends Parent{    
 public Child(){
  System.out.println("Child Constructor");
 }
}

public class MainClass {

 public static void main(String[] args){
  try {

   /****** SERIALIZATION ******/
   Child c = new Child();
   ByteArrayOutputStream baos = new ByteArrayOutputStream();
   ObjectOutputStream oos = new ObjectOutputStream(baos);

   System.out.println("Serializing Object...");
   oos.writeObject(c);
   oos.flush();
   baos.flush();
   oos.close();
   baos.close();

   /****** DE-SERIALIZATION ******/
   ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
   ObjectInputStream ois = new ObjectInputStream(bais);
   System.out.println("Deserializing Object...");
   Child deserializedChild = (Child)ois.readObject();

  } catch (Exception ex){
   ex.printStackTrace();
  }
 }

}
Output :
Parent Constructor
Child Constructor
Serializing Object...
Deserializing Object...


Explanation:
No constructor is called in Deserializing process. How this is possible? If the constructor is not called then how the new Child object "deserializedChild" is created. 
Now the question is "Is there a way to create object without calling constructor of a class?"

Let's answer all questions one by one. 

Java Deserializing process says, "For serializable objects, the no-arg constructor for the first non-serializable supertype is run."

Lets simplify above line, It means during deserialization process, JVM checks the inheritance class hierarchy of instance in process. 

It checks, if the Class instance in process has implemented Serializable interface, If yes, then JVM will check Parent class(If any) of the instance to see if Parent has implemented Serializable interface, If yes, then JVM continues to check all its Parents upwards till it encounters a class which doesn't implement Serializable interface. If all inheritance hierarchy of instance has implemented Serializable interface as one shown above then JVM will end up at default extended Object class which doesn't implemented Serializable interface. So it will create a instance of Object class by calling a default constructor of Object class.

So in above example, JVM will first check whether Child class has implemented Serializable interface, Yes, it has implemented(through Super class-Sub class hierarchy).
Now, JVM will check whether Child class parent that is Parent class has implemented Serializable interface, Yes, it has implemented. 
Now, JVM will check whether Parent class parent that is default Object class has implemented Serializable interface, No, it has not implemented, So JVM will stop further check.
It will create instance of Object class by invoking its default constructor and with the help of created instance, it creates instance of Parent and Child class using newConstructorForSerialization() method of ReflectionFactory class which internally create instance without invoking constructor of class.

So, In Deserialization process, Constructor of class may be invoked or may not be based on whether class has implemented Serializable interface or not.

Lets see one example and things will be more clear.
class A{
 private int a=10;
 public A(){
  System.out.println("A Constructor");
 }
 public int getA() {
  return a;
 }
 public void setA(int a) {
  this.a = a;
 }
}

class B extends A{
 private int b=15;
 public B(){
  System.out.println("B Constructor");
 }
 public int getB() {
  return b;
 }
 public void setB(int b) {
  this.b = b;
 }
}

class C extends B implements Serializable{
 private int c=25;
 public C(){
  System.out.println("C Constructor");
 }
 public int getC() {
  return c;
 }
 public void setC(int c) {
  this.c = c;
 }
}

class D extends C{
 private int d=30;
 public D(){
  System.out.println("D Constructor");
 }
 public int getD() {
  return d;
 }
 public void setD(int d) {
  this.d = d;
 }
}

public class MainClass {

 public static void main(String[] args){
  try {

   /****** SERIALIZATION ******/
   D d = new D();
   d.setA(100);
   d.setB(101);
   d.setC(102);
   d.setD(103);
   
   ByteArrayOutputStream baos = new ByteArrayOutputStream();
   ObjectOutputStream oos = new ObjectOutputStream(baos);

   System.out.println("Serializing Object...");
   oos.writeObject(d);
   oos.flush();
   baos.flush();
   oos.close();
   baos.close();

   /****** DE-SERIALIZATION ******/
   ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
   ObjectInputStream ois = new ObjectInputStream(bais);
   System.out.println("Deserializing Object...");
   D deserializedD = (D)ois.readObject();
   
   System.out.println(deserializedD.getA());
   System.out.println(deserializedD.getB());
   System.out.println(deserializedD.getC());
   System.out.println(deserializedD.getD());

  } catch (Exception ex){
   ex.printStackTrace();
  }
 }
}

 
Output:
A Constructor
B Constructor
C Constructor
D Constructor
Serializing Object...
Deserializing Object...
A Constructor
B Constructor
10
15
102
103
 


Constructor of A and B class is invoked and that is why data of class A and B is set by calling standard constructor whereas for class C and D data is set not by calling constructor but by the data which was present in serialized stream due to which it preserved 102 and 103 which was initialized before serialization.


Question 10: 
During deserialization process, it is said that the no-arg constructor for the first non-serializable supertype is run, what if that class doesn't has default constructor, is it a compile time problem or a run time exception?
 
class A{
 private int a=10;
 public A(){
  System.out.println("A Constructor");
 }
 public int getA() {
  return a;
 }
 public void setA(int a) {
  this.a = a;
 }
}

class B extends A{
 private int b=15;
 public B(int b){  //No default Constructor Present
  System.out.println("B Constructor");
 }
 public int getB() {
  return b;
 }
 public void setB(int b) {
  this.b = b;
 }
}

class C extends B implements Serializable{
 private int c=25;
 public C(){
  super(500);
  System.out.println("C Constructor");
 }
 public int getC() {
  return c;
 }
 public void setC(int c) {
  this.c = c;
 }
}

class D extends C{
 private int d=30;
 public D(){
  System.out.println("D Constructor");
 }
 public int getD() {
  return d;
 }
 public void setD(int d) {
  this.d = d;
 }
}

public class MainClass {

 public static void main(String[] args){
  try {

   /****** SERIALIZATION ******/
   D d = new D();
   d.setA(100);
   d.setB(101);
   d.setC(102);
   d.setD(103);
   
   ByteArrayOutputStream baos = new ByteArrayOutputStream();
   ObjectOutputStream oos = new ObjectOutputStream(baos);

   System.out.println("Serializing Object...");
   oos.writeObject(d);
   oos.flush();
   baos.flush();
   oos.close();
   baos.close();

   /****** DE-SERIALIZATION ******/
   ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
   ObjectInputStream ois = new ObjectInputStream(bais);
   System.out.println("Deserializing Object...");
   D deserializedD = (D)ois.readObject();
   
   System.out.println(deserializedD.getA());
   System.out.println(deserializedD.getB());
   System.out.println(deserializedD.getC());
   System.out.println(deserializedD.getD());

  } catch (Exception ex){
   ex.printStackTrace();
  }
 }

}
Output :
A Constructor
B Constructor
C Constructor
D Constructor
Serializing Object...
Deserializing Object...
java.io.InvalidClassException: D; no valid constructor


Explanation:
First class in the inheritance hierarchy which doesn't implement Serializable interface is B and it doesn't has Default Constructor in our example.
So, from compilation standpoint there is no issue and things works fine. 
During runtime when JVM tries to create instance of class B at that time it will try to call default constructor of class B and it will unable to find due to which it throws exception at Runtime.

Below is perfectly valid deserialization scenario and from below example you will come to know the actual meaning of line which says, "During deserialization, the no-arg constructor for the first non-serializable class should be present"
In below example, the first class which is non-serializable is B, which is having default constructor but its parent that is A is not having default constructor and that is fine because JVM only need no-arg constructor of only first non-serializable class.
 
class A{
 private int a=10;
 public A(int a){ // No default constructor
  System.out.println("A Constructor");
 }
 public int getA() {
  return a;
 }
 public void setA(int a) {
  this.a = a;
 }
}

class B extends A{
 private int b=15;
 public B(){
  super(500);  
  System.out.println("B Constructor");
 }
 public int getB() {
  return b;
 }
 public void setB(int b) {
  this.b = b;
 }
}

class C extends B implements Serializable{
 private int c=25;
 public C(){
  System.out.println("C Constructor");
 }
 public int getC() {
  return c;
 }
 public void setC(int c) {
  this.c = c;
 }
}

class D extends C{
 private int d=30;
 public D(){
  System.out.println("D Constructor");
 }
 public int getD() {
  return d;
 }
 public void setD(int d) {
  this.d = d;
 }
}

public class MainClass {

 public static void main(String[] args){
  try {

   /****** SERIALIZATION ******/
   D d = new D();
   d.setA(100);
   d.setB(101);
   d.setC(102);
   d.setD(103);
   
   ByteArrayOutputStream baos = new ByteArrayOutputStream();
   ObjectOutputStream oos = new ObjectOutputStream(baos);

   System.out.println("Serializing Object...");
   oos.writeObject(d);
   oos.flush();
   baos.flush();
   oos.close();
   baos.close();

   /****** DE-SERIALIZATION ******/
   ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
   ObjectInputStream ois = new ObjectInputStream(bais);
   System.out.println("Deserializing Object...");
   D deserializedD = (D)ois.readObject();
   
   System.out.println(deserializedD.getA());
   System.out.println(deserializedD.getB());
   System.out.println(deserializedD.getC());
   System.out.println(deserializedD.getD());

  } catch (Exception ex){
   ex.printStackTrace();
  }
 }

}

Output:
A Constructor
B Constructor
C Constructor
D Constructor
Serializing Object...
Deserializing Object...
A Constructor
B Constructor
10
15
102
103

You may also like to see


Important Java Multithreading Interview Questions-Answers

How is ambiguous overloaded method call resolved in java?

Exception Handling Interview Question-Answer

Type Casting Interview Questions In Java

Method Overriding rules in Java

Java Interface interview questions and answers

Enjoy !!!! 

If you find any issue in post or face any error while implementing, Please comment.

Post a Comment