Java配列リフレクション:isArrayとinstanceof


回答:


203

ほとんどの場合、instanceof演算子を使用して、オブジェクトが配列であるかどうかをテストする必要があります。

一般に、コンパイル時にわかっている特定の型にダウンキャストする前に、オブジェクトの型をテストします。たとえば、Integer[]やで動作するコードを書いた可能性がありint[]ます。次の方法でキャストを保護する必要がありますinstanceof

if (obj instanceof Integer[]) {
    Integer[] array = (Integer[]) obj;
    /* Use the boxed array */
} else if (obj instanceof int[]) {
    int[] array = (int[]) obj;
    /* Use the primitive array */
} else ...

JVMレベルでは、instanceofオペレーターは特定の「instanceof」に変換されますバイトコードにます。これは、ほとんどのJVM実装で最適化されています。

まれに、リフレクションを使用して、不明なタイプのオブジェクトグラフをトラバースする場合があります。このような場合isArray()、コンパイル時にコンポーネントの種類がわからないため、この方法が役立ちます。たとえば、ある種のシリアル化メカニズムを実装していて、タイプに関係なく、配列の各コンポーネントを同じシリアル化メソッドに渡すことができる場合があります。

2つの特殊なケースがあります。null参照とプリミティブ配列への参照です。

null参照はinstanceof結果を引き起こしfalse、がをisArrayスローしNullPointerExceptionます。

プリミティブ配列に適用すると、右側のオペランドのコンポーネントタイプがコンポーネントタイプと正確に一致しない限り、instanceofyields falseが発生します。対照的に、isArray()trueすべてのコンポーネントタイプに対して返されます。


7
ええ、でもそれはどれほどの違いをもたらすのでしょうか?それは、マイクロ最適化のように思えます。
マイケル・マイヤーズ

2
@Dimsあなたが主張されている場合obj instanceof int[]利回りはfalseあなたが割り当てるときint[]obj、あなたは間違っています。
エリクソン2013

4
申し訳ありませんが、私はその意味obj instanceof Object[]収量をfalse場合Object obj = new int[7]
2013

3
そう、Javaでは、プリミティブデータ型はオブジェクトではなく、拡張もしないjava.lang.Objectので、それは理にかなっています。ただしinstanceof、プリミティブ配列のテストには引き続き使用できます。
エリクソン2013

4
-1:一般に、プリミティブ配列配列なので、呼び出しisArray()を使用する必要があります。オブジェクトの配列のみを持つ非常に一般的ではない特殊なケースでinstanceofは、高性能の代替手段を提供します。
Sam Harwell 2013

33

後者の場合、objがnullの場合、NullPointerExceptionではなくfalseが返されます。


8

objint[]言うタイプの場合、その配列には配列Classがありますが、のインスタンスにはなりませんObject[]。何だからあなたがやりたいですobj。キャストする場合は、を使用してくださいinstanceof。リフレクションを使用する場合は、を使用します.getClass().isArray()


4

getClass().isArray() Sun Java 5または6 JREでは、IBMよりも大幅に遅くなります。

そのため、clazz.getName().charAt(0) == '['Sun JVMの方が高速です。


10
リンクできる統計、事例研究、またはその他の証拠はありますか?
David Citron

4

最近、GroovyアプリケーションをJDK 5からJDK 6にアップグレードする際に問題isArray()が発生しました。JDK6での使用が失敗しました:

MissingMethodException:
No signature of sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl.isArray() ...

instanceof Object[]これを修正しました。


これは意味がありません。isArrayはのメソッドでありClass、ではないTypeので、もちろんGenericArrayTypeImplそのメソッドはありません。そして、getClass非を返すことはできませんClass Type、あなた(またはGroovyの??)がこれを取得するために行わ何か間違っている必要がありますので、すべては仮定のように、TypeですClass
kaqqao 2017

3

Java配列リフレクションは、「instanceof」を実行できるクラスのインスタンスがない場合に使用します。たとえば、JPAのようにクラスの新しいインスタンスに値を注入する、ある種の注入フレームワークを作成している場合は、isArray()機能を使用する必要があります。

12月の初めにこれについてブログに書いた。 http://blog.adamsbros.org/2010/12/08/java-array-reflection/


2

反射ソリューションと非反射ソリューションのどちらかを選択する場合は、反射クラス(クラスオブジェクトを含む)を選択しないでください。それが「間違っている」などというわけではありませんが、反射に関連するものは一般にあまり明確ではなく、あまり明確ではありません。


えーと、まあ、「instanceof」も一種のリフレクション(または、少なくとも内省)ですが、私はあなたの要点を理解します。
David Citron

また、通常は遅くなります。
Mad Physicist

0

2つの間に見つけられる動作に違いはありません(明らかなnullケースを除いて)。どちらのバージョンを好むかについては、2番目のバージョンを使用します。これは、Javaでこれを行う標準的な方法です。

String[] instanceof Object[]trueであるため)コードの読者を混乱させる場合は、コードレビューアがコードについて何度も尋ねる場合は、最初のコードを使用してより明確にすることができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.