質問の歴史
instanceof演算子は、型キャストの前にオブジェクトが特定の型(クラスまたはインターフェース)に属しているかどうかを確認するためにJavaに導入されました。これは、継承、ポリモーフィズム、および異種オブジェクトのコレクションの処理において重要となりました。
問題
型の確認なしにキャストを行うとClassCastExceptionを引き起こす可能性があります。instanceofを不適切に使用すると、コードのアーキテクチャが悪化し、ポリモーフィズムの代わりに頻繁に使用されるといったアンチパターンに繋がる可能性があります。
解決策
instanceof演算子は、オブジェクトがnullでなく、確認される型に属しているか、指定されたインターフェースを実装している場合にtrueを返します。
コードの例:
Object obj = "Hello"; if (obj instanceof String) { String str = (String) obj; System.out.println(str.toUpperCase()); }
主な特徴:
obj == nullの時、obj instanceof SomeClassは何を返しますか?
instanceofはオブジェクトがnullの場合、確認された型に関わらず常にfalseを返します。これはNullPointerExceptionを防ぐために重要です。
interfaceに属するかどうかをinstanceofで確認できますか?
はい。instanceofは、オブジェクトが必要なインターフェースを実装しているかどうかを確認するために使用されます。
コードの例:
Runnable r = () -> {}; System.out.println(r instanceof Runnable); // true
クラスが--release 16+でコンパイルされ、instanceofのパターンマッチングが導入されている場合はどうなりますか?
Java 16+では、instanceof演算子はパターンマッチングをサポートしており、チェックで変数を直接指定して明示的なキャストを回避できます。
コードの例:
Object obj = "Test string"; if (obj instanceof String str) { System.out.println(str.length()); }
大規模プロジェクトでは、ビジネスロジックをif (obj instanceof X)...のシリーズで構築しましたが、メソッドのオーバーライドは行いませんでした。これによりメンテナンスが複雑化し、新しいタイプの出現に対してすべてのチェックを変更する必要がありました。
利点:
欠点:
類似のプロジェクトでは、拡張可能な階層のために抽象メソッドを使用し、instanceofは特別なエッジケースの確認だけに使用しました。
利点:
欠点: