it-swarm.com.de

Java Array Reflexion: isArray vs. instanceof

Gibt es einen Präferenz- oder Verhaltensunterschied zwischen der Verwendung von:

if(obj.getClass().isArray()) {}

und

if(obj instanceof Object[]) {}

?

171
David Citron

In den meisten Fällen sollten Sie den Operator instanceof verwenden, um zu testen, ob ein Objekt ein Array ist.

Im Allgemeinen testen Sie den Typ eines Objekts, bevor Sie ihn auf einen bestimmten Typ übertragen, der zum Zeitpunkt der Kompilierung bekannt ist. Zum Beispiel haben Sie vielleicht Code geschrieben, der mit einem Integer[] Oder einem int[] Arbeiten kann. Sie möchten Ihre Darsteller mit instanceof schützen:

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 ...

Auf der JVM-Ebene übersetzt der Operator instanceof in einen bestimmten "instanceof" Byte-Code, der in den meisten JVM-Implementierungen optimiert ist.

In seltenen Fällen verwenden Sie möglicherweise Reflexion, um ein Objektdiagramm unbekannter Typen zu durchlaufen. In solchen Fällen kann die isArray() -Methode hilfreich sein, da Sie den Komponententyp beim Kompilieren nicht kennen. Sie können beispielsweise einen Serialisierungsmechanismus implementieren und jede Komponente des Arrays unabhängig vom Typ an dieselbe Serialisierungsmethode übergeben.

Es gibt zwei Sonderfälle: Nullverweise und Verweise auf primitive Arrays.

Eine Nullreferenz bewirkt, dass instanceof zu false führt, während isArray ein NullPointerException auslöst.

Auf ein primitives Array angewendet, ergibt instanceoffalse, sofern der Komponententyp auf dem rechten Operanden nicht genau mit dem Komponententyp übereinstimmt. Im Gegensatz dazu gibt isArray()true für jeden Komponententyp zurück.

199
erickson

Im letzteren Fall, wenn obj null ist, erhalten Sie keine NullPointerException, sondern eine false.

32
Burkhard

Wenn obj vom Typ int[] Ist, hat dies ein Array Class, ist jedoch keine Instanz von Object[]. Also, was wollen Sie mit obj machen. Wenn du es wirken willst, gehe mit instanceof. Wenn Sie Reflection verwenden möchten, verwenden Sie .getClass().isArray().

Ich bin kürzlich auf ein Problem gestoßen, bei dem ein Upgrade einer Groovy-Anwendung von JDK 5 auf JDK 6 durchgeführt wurde. Die Verwendung von isArray() ist in JDK6 fehlgeschlagen:

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

Ändern zu instanceof Object[] das behoben.

5
dturanski

getClass().isArray() ist unter Sun Java 5 oder 6 JRE) erheblich langsamer als unter IBM.

So viel, dass die Verwendung von clazz.getName().charAt(0) == '[' unter Sun JVM schneller ist.

4

Java Array Reflection ist für Fälle vorgesehen, in denen keine Instanz der Klasse verfügbar ist, auf der "instanceof" ausgeführt werden kann. Wenn Sie beispielsweise ein Injection-Framework schreiben, das Werte in eine neue Instanz einer Klasse einfügt, wie es JPA tut, müssen Sie die isArray () -Funktionalität verwenden.

Ich habe früher im Dezember darüber gebloggt. http://blog.adamsbros.org/2010/12/08/Java-array-reflection/

3

Wenn Sie jemals die Wahl zwischen einer reflektierenden und einer nicht reflektierenden Lösung haben, wählen Sie niemals die reflektierende Lösung (die Objekte der Klasse umfasst). Es ist nicht so, dass es "falsch" ist oder so, aber alles, was mit Reflektion zu tun hat, ist im Allgemeinen weniger offensichtlich und weniger klar.

2
Bill K

Es gibt keinen Unterschied im Verhalten, den ich zwischen den beiden feststellen kann (außer dem offensichtlichen Null-Fall). Welche Version ich bevorzugen würde, würde ich mit der zweiten gehen. Dies ist die Standardmethode in Java.

Wenn es die Leser Ihres Codes verwirrt (weil String[] instanceof Object[] ist wahr), möchten Sie möglicherweise die erste verwenden, um expliziter zu werden, wenn die Codeüberprüfer immer wieder danach fragen.

0
hazzen