Javaのinstanceof演算子について。
|
|
instanceofは、オブジェクトが該当クラス(を継承している)かどうかを判断する演算子。
該当クラスであれば真(true)。
Java16(プレビュー版はJava14)でパターンマッチング機能が加わった。
instanceofは、目的のクラスへ代入可能であることを確認する(正当な参照型のナローイング変換が可能であることをチェックする)のに使う。
insntaceofの左辺には値(オブジェクト)、右辺にはクラス名(インターフェース名や列挙名等を含む)を書く。
以下のような使われ方をすることが多い。
Object obj = 〜; if (obj instanceof Type) { //「obj instanceof Type」がtrueならば Type t = (Type)obj; // objはTypeのインスタンスなので、Typeへキャストできる 〜 }
int len = (obj instanceof String) ? ((String) obj).length() : 0;
なお、対象オブジェクト(instanceofの左辺値)がnullの場合は、instanceofの結果はfalseになる。
例として、以下のようなクラスやインターフェースが定義されているとする。
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 |
Java16(プレビュー版はJava14)で、insntanceofにパターンマッチング機能が加わった。
instanceofで型をチェックするのと同時に、その型の変数を定義できる。
if (値 instanceof 型 変数) { // 変数がその型として使える }
パターンマッチングの例 | 従来のコーディング |
---|---|
if (obj instanceof String s) { |
if (obj instanceof String) { |
パターンマッチングの例 | 従来のコーディング | 備考 |
---|---|---|
Object obj = 〜; |
Object obj = 〜; |
instanceofでマッチした場合の変数が直接定義できる。 (objがnullの場合はそもそもinstanceofはfalseなのでマッチしない) |
Object obj = 〜; |
instanceofで定義した変数に再代入できる。 | |
String s = 〜; |
常に真となるクラスを指定すると、コンパイルエラーになる。 | |
if (obj instanceof String s) { |
else部では変数は使用できない。 | |
var s
= 123; |
if文の前で同名の変数を定義していた場合、 then部ではinstanceofで定義した変数となるが else部では外側で定義されていた変数がそのまま使用できる。 まぎらわしいので、こういう使い方はやめた方が良さそう。 |
|
if (!(obj instanceof String s)) { |
if (!(obj instanceof String)) { |
ifの条件式を否定にした場合は、else部で変数を使用できる。 (then部では変数を使用できない) |
if (obj instanceof String s && !s.isEmpty()) { |
if (obj instanceof String &&
!((String)obj).isEmpty()) { |
&&を使って、マッチした変数を後ろで使うことが出来る。 |
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; |