Saturday 31 March 2012

instanceof operator in Java

The instanceof operator compares an object to a specified type. You can use it to test at run-time if an object is an instance of a class, an instance of a subclass, or an instance of a class that implements a particular interface.

The syntax of the instanceof operator is
Object_reference instanceof ClassName/InterfaceName

The instanceof operation returns boolean value ,either true or false.

The instanceof returns true, if the object referred to by the variable on the left side of the operator passes the IS-A test for the class or interface type on the right side.
Even if the object being tested is not an actual instantiation of the class type on
the right side of the operator, instanceof will still return true if the object being
compared is assignment compatible with the type on the right.


At compile time it checks whether the type of reference variable on the left and the class or interface on the left are in the same inheritance hierarchy.Else compile-time error occurs.For example


public class Main {

    public static void main(String args[]) {

        String s = "Hello";

        System.out.println(s instanceof StringBuffer);

    }
}


The compile-time error occurs.Because String and StringBuffer are not in the same inheritance hierarchy.The compiler identifies that, there is no chance for a reference variable of type String referring an object of type StringBuffer.

At run-time it checks whether the object referred by the reference variable on the left is compatible with the class or interface on the right and returns true if it is compatible.Else returns false.The compatible type means the object type on the left should pass the IS-A test for the class or interface type on the right.I.e.

The instanceof returns true in the following three scenarios.

  1. The object being testing is an actual instantiation of the class on the right.
  2. The object being tested is a subtype of the class on the right
  3. The class of object being tested implements the interface on the right directly or indirectly.

 
Let us discuss above three scenarios with examples

1) The object being testing is an actual instantiation of the class on the right.


public class Main {

    public static void main(String args[]) {

        String s = "Hello";

        System.out.println("s instanceof String= " + (s instanceof String));

    }
}


The output is

s instanceof String= true

Here the object s is an actual instantiation of the class type String on the right so returns true.

2) The object being tested is a subtype of the class on the right



class Vehicle {
}

class Bus extends Vehicle {
}

class Car extends Vehicle {
}

public class Main {

    public static void main(String args[]) {

        Vehicle vehicle=new Vehicle();
        Car car=new Car();
        Bus bus=new Bus();

        System.out.println("vehicle instanceof Vehicle= " + (vehicle instanceof Vehicle ));
        System.out.println("car instanceof Car= " + (car instanceof Car ));
        System.out.println("bus instanceof Bus= " + (bus instanceof Bus ));
       
        System.out.println("vehicle instanceof Object= "+(vehicle instanceof Object));
        System.out.println("car instanceof Vehicle= "+(car instanceof Vehicle));
        System.out.println("bus instanceof Vehicle= "+(bus instanceof Vehicle));
       
        System.out.println("vehicle instanceof Car= "+(vehicle instanceof Car));
        System.out.println("vehicle instanceof Bus= "+(vehicle instanceof Bus));

    }
}


The output is

vehicle instanceof Vehicle= true
car instanceof Car= true
bus instanceof Bus= true
vehicle instanceof Object= true
car instanceof Vehicle= true
bus instanceof Vehicle= true
vehicle instanceof Car= false
vehicle instanceof Bus= false

Notice that car instanceof Vehicle returns true because car 's class type Car is a sub class of the class Vehicle on the right.Similarly vehicle instanceof Object and bus instanceof Vehicle return true.


The vehicle instanceof Car and vehicle instanceof Bus return false because vehicle's class type Vehicle is the super class of both Car and Bus on the right side.


Note: Any object reference except null will evaluate to true if you use the instanceof operator against type Object .

public class Main {

    public static void main(String args[]) {

        String s = "Hello";

        System.out.println("s instanceof Object= " + (s instanceof Object));

    }
}

The output is

s instanceof Object= true

Object is the base class of all the classes in Java so returns true.

Note:The null is not an instance of any class in Java.For example

public class Main {

    public static void main(String args[]) {

        String s = null;
        System.out.println("s instanceof Object= " + (s instanceof Object));
        System.out.println("null instanceof String= " + (null instanceof String));
        System.out.println("null instanceof Object= " + (null instanceof Object));

    }
}

The output is

s instanceof Object= false
null instanceof String= false
null instanceof Object= false

3) The object's class implements the interface directly or indirectly.


An indirect implementation occurs when one of an object's super classes implements an interface, but the actual class of the instance does not—for example,


interface I {
}

class A implements I {
    // directly implemented interface I
}

class B extends A {
    // indirectly implemented interface I
}

public class Main {

    public static void main(String args[]) {

        A a = new A();
        B b = new B();

        System.out.println("a instanceof I= " + (a instanceof I));
        System.out.println("b instanceof I= " + (b instanceof I));

    }
}


The output is

a instanceof I= true
b instanceof I= true


Use of instanceof operator


The instanceof operator can be used to avoid ClassCastException while performing the down casting of reference variables.
Please go through ClassCastException in Java to learn more about reference variable casting and ClassCastException.

For example a display() method to iterate the elements in List,Set and Map.

import java.util.*;

public class Main {

    public static void main(String args[]) {
        List< String > nameList = new ArrayList< String >();
        nameList.add("John");
        nameList.add("Anna");
        nameList.add("Roy");

        Set< String > langSet = new HashSet< String >();
        langSet.add("C");
        langSet.add("C++");
        langSet.add("Java");

        Map< String, String > capitals = new HashMap< String, String >();
        capitals.put("India", "Delhi");
        capitals.put("Pakistan", "Islamabad");
        capitals.put("Srilanka", "Colombo");
        display(nameList);
        display(langSet);
        display(capitals);
    }

    /* To display List,Set and Map elements */

    static void display(Object c) {
        if (c instanceof List) {
            List< String > nameList = (List) c;   //down casting
            System.out.println("Printing List");
            for (String name : nameList) {
                System.out.println(name);
            }

        } else if (c instanceof Set) {
            Set< String > langSet = (Set) c;   //down casting
            System.out.println("Printing Set");
            for (String lang : langSet) {
                System.out.println(lang);
            }

        } else if (c instanceof Map) {
            Map< String, String > capitalMap = (Map) c;   //down casting
            Set< String > keys = capitalMap.keySet();
            System.out.println("Printing Map");
            for (String key : keys) {
                System.out.println("Country:" + key + " Capital City:"
                        + capitalMap.get(key));
            }
        }

    }
}


The output is

Printing List
John
Anna
Roy
Printing Set
C
C++
Java
Printing Map
Country:Srilanka Capital City:Colombo
Country:Pakistan Capital City:Islamabad
Country:India Capital City:Delhi

In order to generalize the display method for all the classes and interfaces in the collection framework,display receives a reference of class type Object as parameter.Object class is the base class of all classes in java,so reference of any class type can be cast to Object type.Only at run-time the system can identify that parameter c is referring which object type.So if you do a down casting without checking the object type of c, there is a chance for ClassCastException.


For example

import java.util.*;

public class Main {

    public static void main(String args[]) {

        Set< String > langSet = new HashSet< String >();
        langSet.add("C");
        langSet.add("C++");
        langSet.add("Java");

        displayList(langSet);
    }

    static void displayList(Collection< String > c) {

        List< String > nameList = (List) c;
        System.out.println("Printing Element");
        for (String name : nameList) {
            System.out.println(name);
        }

    }
}


The output is

Exception in thread "main" java.lang.ClassCastException: java.util.HashSet cannot be cast to java.util.List
    at Main.displayList(Main.java:18)
    at Main.main(Main.java:12)

Here the compiler failed to identify that reference variable c is referring HashSet type  not the List type.In order to avoid these type of problems do a instanceof check before performing the down casting.

The links you may like

Casting Reference Variables- Downcasting, Upcasting  

ClassCastException in Java

No comments:

Post a Comment