S-JIS[2021-03-21] 変更履歴

instanceof

Javaのinstanceof演算子について。


概要

instanceofは、オブジェクトが該当クラス(を継承している)かどうかを判断する演算子。
該当クラスであれば真(true)。

Java16(プレビュー版はJava14)でパターンマッチング機能が加わった。


instanceof

instanceofは、目的のクラスへ代入可能であることを確認する(正当な参照型のナローイング変換が可能であることをチェックする)のに使う。

insntaceofの左辺には値(オブジェクト)、右辺にはクラス名インターフェース名列挙名等を含む)を書く。

以下のような使われ方をすることが多い。

	Object obj = 〜;
	if (obj instanceof Type) {	//「obj instanceof Type」がtrueならば
		Type t = (Type)obj;	// objTypeのインスタンスなので、Typeへキャストできる
		〜
	}
	int len = (obj instanceof String) ? ((String) obj).length() : 0;

なお、対象オブジェクト(instanceofの左辺値)がnullの場合は、instanceofの結果はfalseになる。

リフレクションで型を判断する方法


instanceofの例

例として、以下のようなクラスやインターフェースが定義されているとする。

interface I {}
class S {}
class A extends S implements I {}
class B {}
class C extends B implements I {}

A a = new A();
B b = new B();
B b2 = new C(); // CはBを継承しているので、変数の型をBに出来る
Object objA = new A();
結果 備考
a instanceof A true  
a instanceof S true  
a instanceof I true  
a instanceof B コンパイルエラー 変数のクラスAとクラスBは継承関係が無いので、コンパイル時点で変換不可だと分かる。
b instanceof A コンパイルエラー 変数のクラスBとクラスAは継承関係が無いので、コンパイル時点で変換不可だと分かる。
b instanceof S コンパイルエラー 変数のクラスBとクラスSは継承関係が無いので、コンパイル時点で変換不可だと分かる。
b instanceof I false  
b instanceof B true  
b instanceof C false  
b2 instanceof I true instanceofでチェックされるのは、変数に入っているインスタンスのクラスであり、
変数のクラスではない。
b2 instanceof B true
b2 instanceof C true
objA instanceof A true  
objA instanceof S true  
objA instanceof I true  
objA instanceof B false  
null instanceof A false  

パターンマッチングinstanceof

Java16(プレビュー版はJava14)で、insntanceofにパターンマッチング機能が加わった。

instanceofで型をチェックするのと同時に、その型の変数を定義できる。

	if (値 instanceof 型 変数) {
		// 変数がその型として使える
	}
パターンマッチングの例 従来のコーディング
if (obj instanceof String s) {
  // sがStringとして使える
}
if (obj instanceof String) {
  String s = (String)obj;
  〜
}

パターンマッチングinstanceofの例

パターンマッチングの例 従来のコーディング 備考
Object obj = 〜;
if (obj instanceof String s) {

  System.out.println(s.length());
}
Object obj = 〜;
if (obj instanceof String) {
  String s = (String)obj;
  System.out.println(s.length());
}
instanceofでマッチした場合の変数が直接定義できる。
(objがnullの場合はそもそもinstanceofはfalseなのでマッチしない)
Object obj = 〜;
if (obj instanceof String s) {
  System.out.println(s);
  s = "abc";
  System.out.println(s);
}
  instanceofで定義した変数に再代入できる。
String s = 〜;
if (s instanceof Object obj) {
}
  常に真となるクラスを指定すると、コンパイルエラーになる。
if (obj instanceof String s) {
  System.out.println(s.length());
} else {
  System.out.println(s); ←エラー
}
  else部では変数は使用できない。
var s = 123;
if (obj instanceof String s) {
  System.out.println(s.length());
} else {
  System.out.println(s);
}
  if文の前で同名の変数を定義していた場合、
then部ではinstanceofで定義した変数となるが
else部では外側で定義されていた変数がそのまま使用できる。
まぎらわしいので、こういう使い方はやめた方が良さそう。
if (!(obj instanceof String s)) {
  System.out.println(obj.getClass());
} else {

  System.out.println(s.length());
}
if (!(obj instanceof String)) {
  System.out.println(obj.getClass());
} else {
  String s = (String)obj;
  System.out.println(s.length());
}
ifの条件式を否定にした場合は、else部で変数を使用できる。
(then部では変数を使用できない)
if (obj instanceof String s && !s.isEmpty()) {

  System.out.println(s.length());
}
if (obj instanceof String && !((String)obj).isEmpty()) {
  String s = (String)obj;
  System.out.println(s.length());
}
&&を使って、マッチした変数を後ろで使うことが出来る。
return (obj instanceof String s) && !s.isEmpty(); return (obj instanceof String) && !((String)obj).isEmpty();
var len = (obj instanceof String s) ? s.length() : 0; var len = (obj instanceof String) ? ((String)obj).length() : 0; 条件演算子(三項演算子)でもinstanceofのパターンマッチングが使える。
var s = -1;
var len = (obj instanceof String s) ? s.length() : s;
 

Java目次へ戻る / 新機能へ戻る / 技術メモへ戻る
メールの送信先:ひしだま