Monday, 6 March 2017

instanceof Operator in Java

In your application sometimes you have a situation when you would like to know the type of an object during run time. It is evidently important when you have a parent-child relationship, an inheritance hierarchy with a parent class and more than one child classes.

A super type can hold reference to an object of itself or the sub-types. But doing the opposite, when you want a conversion from super-type to sub-type, you will need type casting.

As example, if there is class A and two child classes class B and class C, then object of type A can refer to object of type B or to an object of type C.

A a;
B b = new B();
C c = new C();
a = b; 
b = a; // results in compile-time error (Type mismatch)

This (a = b) can be done with out any need of casting.
But doing the opposite (b = a;) will need casting. What you will have to do is -

b = (B) a;
a = c;

and for class C object c = (C)a;

Now, in your application if you have a hierarchy where there are many child classes, type casting may cause problem as you may not be knowing the actual type of the object. In this case you need instanceof operator to check the type of the object before doing the casting.

instanceof operator

An object can only be cast to its own class or one of its super-type, if you try to cast to any other object you may either get a compile-time error or a class-cast exception (run-time).

In order to avoid that error it is better to check whether the object can be cast to that type safely or not. For that you can use instanceof operator.

General form of the instanceof operator

obj instanceof type;

Here obj is refrence to an object and type is a class type. This check will return true if obj is of the class type given on the right hand side of the instanceof operator or can be cast into that type safely.

Example using instanceof operator

Here I have a class hierarchy where Payment is an interface and there are two classes CashPayment and CardPayment implementing the Payment interface.

Payment interface

public interface Payment {
 public boolean proceessPayment(double amount);
}

CashPayment class

import org.netjs.examples.interfaces.Payment;

public class CashPayment implements Payment {
 @Override
 public boolean proceessPayment(double amount) {
  System.out.println("Cash payment done for Rs. " + amount);
  return true;
 }
}

CardPayment class

import org.netjs.examples.interfaces.Payment;

public class CardPayment implements Payment {

 @Override
 public boolean proceessPayment(double amount) {
  System.out.println("Card Payment done for Rs. " + amount);
  return true;
 }
 
 public void printSlip(){
  System.out.println("Printing slip for payment" );
 }
}

In CardPayment class, note that, there is an extra method printSlip().

As a good programmer you are trying to write a good, object-oriented principles following code and want to have proper polymorphism. In order to achieve that you will refer the instances of child classes CardPayment and CashPayment through the super type instance Payment. Something similar to what is written below.

import org.netjs.examples.interfaces.Payment;

public class PaymentDemo {

 public static void main(String[] args) {
  PaymentDemo pd = new PaymentDemo();
  Payment payment = new CashPayment();
  pd.doPayment(payment, 100);
  payment = new CardPayment();
  pd.doPayment(payment, 300);
 }
 
 public void doPayment(Payment pd, int amt){
  pd.proceessPayment(amt);
  CardPayment cardPay = (CardPayment)pd;
  cardPay.printSlip();
 }
}

But running this will throw ClassCastException at run time -

Cash payment done for Rs. 100.0
Exception in thread "main" java.lang.ClassCastException: org.netjs.examples.impl.CashPayment cannot be cast to org.netjs.examples.impl.CardPayment
 at org.netjs.examples.impl.PaymentDemo.doPayment(PaymentDemo.java:17)
 at org.netjs.examples.impl.PaymentDemo.main(PaymentDemo.java:10)

What went wrong here is that you want to call printSlip() method only if the instance is of type CardPayment. But doPayment() method of the PaymentDemo class is having Payment (Super class) as the argument which can refer to instances of CardPayment as well as CashPayment.

Here you can use instanceof operator to check if passed reference is actually of type CardPayment, if yes, then only call the printSlip() method.

Code after including instanceof operator

public class PaymentDemo {

 public static void main(String[] args) {
  PaymentDemo pd = new PaymentDemo();
  Payment payment = new CashPayment();
  pd.doPayment(payment, 100);
  payment = new CardPayment();
  pd.doPayment(payment, 300);
 }
 
 public void doPayment(Payment pd, int amt){
  pd.proceessPayment(amt);
  if (pd instanceof CardPayment){
   CardPayment cardPay = (CardPayment)pd;
   cardPay.printSlip();
  }
 }
}

Output

Cash payment done for Rs. 100.0
Card Payment done for Rs. 300.0
Printing slip for payment

Here note how instanceof operator is used to check the type and if appropriate type is there then only condition gets fulfilled.

Points to remember

  1. An object can only be cast to its own class or one of its super-type.
  2. instanceof operator provides you a way to get run time information about the type of the object.
  3. instanceof operator, if used, should be used sporadically. If you are compelled to use instanceof operator a lot that would mean some inherent flaw in the design of your application.
  4. A use case where use of instanceof operator makes sense is trying to write a generalized logic for a class hierarchy, so that your logic can work for any object of the class hierarchy.

That's all for this topic instanceof Operator in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Package in Java
  2. Access modifiers in Java
  3. Encapsulation in Java
  4. Polymorphism in Java
  5. Ternary operator in Java

You may also like -

>>>Go to Java Basics page

No comments:

Post a Comment