Gibt es einen Präferenz- oder Verhaltensunterschied zwischen der Verwendung von:
if(obj.getClass().isArray()) {}
und
if(obj instanceof Object[]) {}
?
Gibt es einen Präferenz- oder Verhaltensunterschied zwischen der Verwendung von:
if(obj.getClass().isArray()) {}
und
if(obj instanceof Object[]) {}
?
Antworten:
In den meisten Fällen sollten Sie den instanceof
Operator verwenden, um zu testen, ob ein Objekt ein Array ist.
Im Allgemeinen testen Sie den Typ eines Objekts, bevor Sie es auf einen bestimmten Typ übertragen, der zur Kompilierungszeit bekannt ist. Zum Beispiel haben Sie vielleicht einen Code geschrieben, der mit einem Integer[]
oder einem funktionieren kann int[]
. Sie möchten Ihre Casts schützen mit 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 ...
Auf JVM-Ebene instanceof
übersetzt der Operator in einen bestimmten "Instanz" -Bytecode, der in den meisten JVM-Implementierungen optimiert ist.
In selteneren Fällen verwenden Sie möglicherweise die Reflexion, um einen Objektgraphen unbekannter Typen zu durchlaufen. In solchen Fällen kann die isArray()
Methode hilfreich sein, da Sie den Komponententyp zur Kompilierungszeit nicht kennen. Möglicherweise implementieren Sie beispielsweise einen Serialisierungsmechanismus und können jede Komponente des Arrays unabhängig vom Typ an dieselbe Serialisierungsmethode übergeben.
Es gibt zwei Sonderfälle: Nullreferenzen und Verweise auf primitive Arrays.
Eine Nullreferenz führt instanceof
zum Ergebnis false
, während die isArray
Würfe a NullPointerException
.
Auf ein primitives Array angewendet instanceof
ergibt sich die Ausbeute, false
sofern der Komponententyp im rechten Operanden nicht genau mit dem Komponententyp übereinstimmt. Im Gegensatz dazu isArray()
wird true
für jeden Komponententyp zurückgegeben.
obj instanceof int[]
Ausbeuten , false
wenn Sie eine zuweisen int[]
zu obj
, Sie irren sich .
obj instanceof Object[]
ergibt false
wenn Object obj = new int[7]
.
java.lang.Object
ist also sinnvoll. Aber instanceof
immer noch für primitive Arrays zum Testen verwendet werden.
isArray()
sollte im Allgemeinen der Aufruf verwendet werden. In dem nicht ganz allgemeinen Sonderfall, nur Arrays von Objekten zu haben, instanceof
bietet sich eine leistungsstarke Alternative an.
Wenn obj
es vom Typ int[]
say ist, dann hat das ein Array, ist Class
aber keine Instanz von Object[]
. Also , was wollen Sie mit zu tun obj
. Wenn Sie es besetzen wollen, gehen Sie mit instanceof
. Wenn Sie Reflexion verwenden möchten, verwenden Sie .getClass().isArray()
.
getClass().isArray()
ist unter Sun Java 5 oder 6 JRE deutlich langsamer als unter IBM.
So viel, dass die Verwendung clazz.getName().charAt(0) == '['
von Sun JVM schneller ist.
Ich bin kürzlich auf ein Problem beim Upgrade einer Groovy-Anwendung von JDK 5 auf JDK 6 isArray()
gestoßen . Die Verwendung in JDK6 ist fehlgeschlagen:
MissingMethodException:
No signature of sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl.isArray() ...
Ändern, um instanceof Object[]
dies zu beheben.
isArray
ist eine Methode von Class
, nicht Type
, also GenericArrayTypeImpl
hat diese Methode natürlich nicht. Und getClass
kann niemals ein Nicht- zurückgeben Class
Type
, also müssen Sie (oder Groovy ??) etwas falsch gemacht haben, um dies zu erreichen, wie die Annahme, dass jeder ein Type
ist Class
.
Java-Array-Reflektion ist für Fälle vorgesehen, in denen keine Instanz der Klasse verfügbar ist, für die "instanceof" ausgeführt werden kann. Wenn Sie beispielsweise eine Art Injection-Framework schreiben, das Werte in eine neue Instanz einer Klasse einfügt, wie dies JPA tut, müssen Sie die isArray () -Funktionalität verwenden.
Ich habe Anfang Dezember darüber gebloggt. http://blog.adamsbros.org/2010/12/08/java-array-reflection/
Wenn Sie jemals die Wahl zwischen einer reflektierenden und einer nicht reflektierenden Lösung haben, wählen Sie niemals die reflektierende (mit Klassenobjekten). Es ist nicht so, dass es "falsch" oder so ist, aber alles, was Reflexion beinhaltet, ist im Allgemeinen weniger offensichtlich und weniger klar.
Es gibt keinen Unterschied im Verhalten, den ich zwischen den beiden finden kann (außer dem offensichtlichen Nullfall). Welche Version ich bevorzugen möchte, würde ich mit der zweiten gehen. Dies ist die Standardmethode in Java.
Wenn es die Leser Ihres Codes verwirrt (weil String[] instanceof Object[]
es wahr ist), möchten Sie möglicherweise den ersten verwenden, um expliziter zu sein, wenn Codeprüfer immer wieder danach fragen.