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
テスト用のコード
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