Javaのinstanceof演算子

Javaのinstanceof演算子に関するメモです。

instanceofの基本

instanceof演算子の演算結果は、左辺のオブジェクトが以下の条件のどれかを満たす場合にtrueとなります。

  • 右辺に指定したクラスのオブジェクトである。
  • 右辺に指定したクラスのサブクラスのオブジェクトである。
  • 右辺に指定したインターフェースの実装クラスである。
  • 右辺に指定したインターフェースの実装クラスのサブクラスである。

instanceof演算子の演算結果がtrueになった場合、左辺のオブジェクトを右辺のクラスにキャストし、メンバにアクセスすることが可能です。

テスト用のコード

import java.io.Serializable;

public class InstanceOfTest1 {
    
    public static void main(String[] args) {
        
        /*
         * NumberクラスはObjectクラスのサブクラスである。
         * IntegerクラスはNumberクラスのサブクラスである。
         * NumberクラスはSerializableインターフェースを実装する。
         */
        
        final Number number = new Integer(100);
        
        if (number instanceof Object) {
            Object x = number;
            System.out.println("Object : " + x);
        }
        
        if (number instanceof Number) {
            Number x = number;
            System.out.println("Number : " + x);
        }
        
        if (number instanceof Integer) {
            Integer x = (Integer)number;
            System.out.println("Integer : " + x);
        }
        
        if (number instanceof Double) {
            Double x = (Double)number;
            System.out.println("Double : " + x);
        }
        
        if (number instanceof Serializable) {
            Serializable x = number;
            System.out.println("Serializable : " + x);
        }
        
        if (number instanceof Runnable) {
            Runnable x = (Runnable)number;
            System.out.println("Runnable : " + x);
        }
        
    }
    
}

実行結果

Object : 100
Number : 100
Integer : 100
Serializable : 100

instanceofとプリミティブ型

instanceof演算子では、プリミティブ型を扱うことはできません。例えば、次のようなコードはコンパイルエラーとなります。

    if (number instanceof int) {
        int x = (int)number;
        System.out.println("int : " + x);
    }

instanceofとnull

instanceof演算子の演算結果は、左辺がnullの場合はfalseになります。

テスト用のコード

public class InstanceOfTest2 {
    
    public static void main(String[] args) {
        
        final Object obj = null;
        
        if (obj instanceof Object) {
            System.out.println("Object");
        } else {
            System.out.println("Not Object");
        }
        
    }
    
}

実行結果

Not Object

Object#getClass()を使った比較

instanceof演算子の代わりにObject#getClass()を使用すると、オブジェクトの型が、指定したクラスに完全に一致するかどうかを判定できます。

テスト用のコード

import java.io.Serializable;

public class InstanceOfTest3 {
    
    public static void main(String[] args) {
        
        final Number number = new Integer(100);
        
        if (number.getClass() == (Class<?>)Object.class) {
            Object x = number;
            System.out.println("Object : " + x);
        }
        
        if (number.getClass() == (Class<?>)Number.class) {
            Number x = number;
            System.out.println("Number : " + x);
        }
        
        if (number.getClass() == (Class<?>)Integer.class) {
            Integer x = (Integer)number;
            System.out.println("Integer : " + x);
        }
        
        if (number.getClass() == (Class<?>)Double.class) {
            Double x = (Double)number;
            System.out.println("Double : " + x);
        }
        
        if (number.getClass() == (Class<?>)Serializable.class) {
            Serializable x = number;
            System.out.println("Serializable : " + x);
        }
        
        if (number.getClass() == (Class<?>)Runnable.class) {
            Runnable x = (Runnable)number;
            System.out.println("Runnable : " + x);
        }
        
    }
    
}

実行結果

Integer : 100

instanceofとジェネリッククラス

instanceofの右辺でのクラス指定でジェネリッククラスを指定する場合は、型としてワイルドカード(?)を指定する必要があります。これは、ジェネリッククラスの型情報が、コンパイル時に無くなっているためです。
次の例では、オブジェクトがList<String>であるかをinstanceofで判断できないため、まず、オブジェクトがList<?>かどうかをチェックし、さらにそのメンバがStringであるかをチェックしています。なお、このチェックでは、Listの場合と、List<Object>でメンバが全てStringだった場合を区別できません。

テスト用のコード

import java.util.ArrayList;
import java.util.List;

public class InstanceOfTest4 {
    
    public static void main(String[] args) {
        
        System.out.println("[Test 1]");
        final Object obj1 = getObject1();
        printStringList(obj1);
        System.out.println();
        
        System.out.println("[Test 2]");
        final Object obj2 = getObject2();
        printStringList(obj2);
        System.out.println();
        
    }
    
    private static Object getObject1() {
        List<String> list = new ArrayList<String>();
        list.add("abc");
        list.add("de");
        list.add("fghij");
        return list;
    }
    
    private static Object getObject2() {
        List<Object> list = new ArrayList<Object>();
        list.add("abc");
        list.add("de");
        list.add("fghij");
        return list;
    }
    
    private static void printStringList(Object obj) {
        if (obj instanceof List<?>) {
            List<?> list = (List<?>)obj;
            
            for (Object o : list) {
                if (o instanceof String) {
                    String s = (String)o;
                    System.out.println(s);
                }
            }
        }
    }
    
}

実行結果

[Test 1]
abc
de
fghij

[Test 2]
abc
de
fghij