Objects.toString() / getClass() / instanceof
| 対応: | Java 1.0(1996) |
|---|
オブジェクトの実際の型を実行時に確認するための演算子・メソッドです。『instanceof』で型チェックを行い、『getClass()』で実際のクラスを取得します。Java 16以降はパターンマッチングでキャストを簡略化できます。
構文
// instanceofで型を確認します(trueなら指定型またはそのサブクラス)
boolean result = オブジェクト instanceof 型名;
// パターンマッチング instanceof(Java 16以降): チェックとキャストを同時に行います
if (オブジェクト instanceof 型名 変数名) {
// 変数名を型名として直接使用できます
}
// 実際のクラスオブジェクトを取得します
Class<?> clazz = オブジェクト.getClass();
// クラスの単純名(パッケージなし)を取得します
String simpleName = オブジェクト.getClass().getSimpleName();
// クラスの完全修飾名を取得します
String fullName = オブジェクト.getClass().getName();
メソッド・演算子一覧
| メソッド / 演算子 | 概要 |
|---|---|
| instanceof 型名 | オブジェクトが指定した型またはそのサブクラスのインスタンスであれば true を返します。null に対しては常に false を返します。 |
| instanceof 型名 変数名 | Java 16以降のパターンマッチング。条件が真の場合に変数に自動キャストされた値を束縛します。 |
| getClass() | 実行時の実際のクラスを Class<?> オブジェクトとして返します。 |
| getClass().getSimpleName() | クラスの単純名(パッケージ部分を除いた名前)を返します。 |
| getClass().getName() | 完全修飾クラス名(例: java.lang.String)を返します。 |
| getClass().getSuperclass() | 直接の親クラスを返します。 |
| getClass().getInterfaces() | 実装しているインターフェースの配列を返します。 |
サンプルコード
GetclassInstanceof.java
class Fighter {}
class KofFighter extends Fighter {}
class OrocFighter extends Fighter {}
class GetclassInstanceof {
public static void main(String[] args) {
// instanceofで型チェックを行います
Object obj = "yagami iori";
System.out.println(obj instanceof String); // 『true』と出力されます
System.out.println(obj instanceof Integer); // 『false』と出力されます
System.out.println(null instanceof String); // 『false』と出力されます(nullはfalse)
// 従来のinstanceof + キャストの書き方です
if (obj instanceof String) {
String s = (String) obj;
System.out.println(s.toUpperCase()); // 『YAGAMI IORI』と出力されます
}
// パターンマッチングinstanceof(Java 16以降)
if (obj instanceof String s) {
System.out.println(s.length()); // 『11』と出力されます
}
// getClass() でクラス情報を取得します
Object num = 42;
System.out.println(num.getClass().getSimpleName()); // 『Integer』と出力されます
System.out.println(num.getClass().getName()); // 『java.lang.Integer』と出力されます
// ポリモーフィズムとinstanceofを組み合わせます
Fighter a = new KofFighter();
System.out.println(a instanceof Fighter); // 『true』と出力されます
System.out.println(a instanceof KofFighter); // 『true』と出力されます
System.out.println(a instanceof OrocFighter); // 『false』と出力されます
// switch文でパターンマッチング(Java 21以降)
Object value = 3.14;
String desc = switch (value) {
case Integer i -> "整数: " + i;
case Double d -> "小数: " + d;
case String s -> "文字列: " + s;
default -> "その他";
};
System.out.println(desc); // 『小数: 3.14』と出力されます
}
}
コンパイルして実行すると次のようになります。
javac GetclassInstanceof.java java GetclassInstanceof true false false YAGAMI IORI 11 Integer java.lang.Integer true true false 小数: 3.14
よくあるミス
よくあるミス1: instanceofとnullチェックを混同する
instanceofはnullに対して常にfalseを返します。「== null」チェックとinstanceofを混同して、nullチェックが不要な箇所で余分なチェックをしたり、逆にnullの場合に処理が漏れることがあります。
GetclassInstanceofNg1.java
class GetclassInstanceofNg1 {
static void greet(Object obj) {
if (obj == null) {
System.out.println("null です");
}
if (obj instanceof String) {
String name = (String) obj;
System.out.println("こんにちは、" + name + "!");
}
}
public static void main(String[] args) {
greet("八神庵");
greet(null);
greet(42);
}
}
コンパイルして実行すると次のようになります。
javac GetclassInstanceofNg1.java java GetclassInstanceofNg1 こんにちは、八神庵! null です
instanceofはnullに対して自動的にfalseを返すため、nullチェックは不要です。instanceofだけで安全に判定できます。
GetclassInstanceofOk1.java
class GetclassInstanceofOk1 {
static void greet(Object obj) {
if (obj instanceof String name) {
System.out.println("こんにちは、" + name + "!");
} else {
System.out.println("文字列ではありません: " + obj);
}
}
public static void main(String[] args) {
greet("草薙京");
greet(null);
greet(42);
}
}
コンパイルして実行すると次のようになります。
javac GetclassInstanceofOk1.java java GetclassInstanceofOk1 こんにちは、草薙京! 文字列ではありません: null 文字列ではありません: 42
よくあるミス2: getClass()で継承関係を確認しようとして意図しない結果になる
getClass()はオブジェクトの実際のクラスだけを返し、継承関係を考慮しません。スーパークラスかどうかを確認したい場合にgetClass()を使うと、サブクラスのオブジェクトが意図通りに判定されません。
GetclassInstanceofNg2.java
class Fighter {}
class KofFighter extends Fighter {}
class GetclassInstanceofNg2 {
public static void main(String[] args) {
Fighter a = new KofFighter();
System.out.println(a.getClass() == Fighter.class);
System.out.println(a instanceof Fighter);
}
}
コンパイルして実行すると次のようになります。
javac GetclassInstanceofNg2.java java GetclassInstanceofNg2 false true
継承関係を含めて型チェックするにはinstanceofを使います。テリー・ボガードがFighterかどうかを確認するように、「〇〇の一種かどうか」はinstanceofで判定します。
GetclassInstanceofOk2.java
class Fighter {}
class KofFighter extends Fighter {}
class GetclassInstanceofOk2 {
static void checkType(Fighter f) {
if (f instanceof KofFighter kf) {
System.out.println("KOFファイター: " + kf.getClass().getSimpleName());
} else {
System.out.println("汎用ファイター: " + f.getClass().getSimpleName());
}
}
public static void main(String[] args) {
checkType(new KofFighter());
checkType(new Fighter());
}
}
コンパイルして実行すると次のようになります。
javac GetclassInstanceofOk2.java java GetclassInstanceofOk2 KOFファイター: KofFighter 汎用ファイター: Fighter
概要
『instanceof』はポリモーフィズムを使ったコードでオブジェクトの実際の型を確認するときに使います。Java 16以降のパターンマッチング構文(instanceof 型名 変数名)を使うと、チェックとキャストを1行で書けて可読性が上がります。
『getClass()』は継承関係を無視して実際のクラスだけを返します。継承を考慮した型チェックには instanceof を使い、厳密に同じクラスかどうかを確認したい場合は getClass() == 型名.class を使ってください。
Objectsクラスのユーティリティメソッドについては『Objects.equals() / Objects.toString() / Objects.requireNonNull()』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。