web-dev-qa-db-fra.com

Java Réflexion sur un tableau: isArray vs instanceof

Existe-t-il une différence de comportement ou de préférence entre l'utilisation de:

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

et

if(obj instanceof Object[]) {}

?

171
David Citron

Dans la plupart des cas, vous devez utiliser l'opérateur instanceof pour vérifier si un objet est un tableau.

Généralement, vous testez le type d'un objet avant de le convertir en un type particulier connu au moment de la compilation. Par exemple, vous avez peut-être écrit un code qui peut fonctionner avec un Integer[] Ou un int[]. Vous voudriez garder vos castes avec 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 ...

Au niveau de la JVM, l’opérateur instanceof est converti en un code spécifique "instanceof" , optimisé dans la plupart des implémentations de JVM.

Dans des cas plus rares, vous pouvez utiliser la réflexion pour parcourir un graphe d'objet de types inconnus. Dans ce cas, la méthode isArray() peut être utile car vous ne connaissez pas le type de composant au moment de la compilation. vous pouvez, par exemple, implémenter une sorte de mécanisme de sérialisation et être capable de transmettre chaque composant du tableau à la même méthode de sérialisation, quel que soit le type.

Il existe deux cas spéciaux: les références nulles et les références à des tableaux primitifs.

Une référence nulle entraînera instanceof comme résultat false, tandis que le isArray lève un NullPointerException.

Appliqué à un tableau primitif, le paramètre instanceof renvoie false à moins que le type de composant de l'opérande de droite ne corresponde exactement au type de composant. En revanche, isArray() renverra true pour tout type de composant.

199
erickson

Dans ce dernier cas, si obj est null, vous n'obtiendrez pas une exception NullPointerException mais une valeur false.

32
Burkhard

Si obj est de type int[], Alors il y aura un tableau Class mais pas une instance de Object[]. Alors, que voulez-vous faire avec obj. Si vous voulez le lancer, utilisez instanceof. Si vous envisagez d'utiliser la réflexion, utilisez .getClass().isArray().

8

J'ai récemment rencontré un problème de mise à niveau d'une application Groovy de JDK 5 à JDK 6. L'utilisation de isArray() a échoué dans JDK6:

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

Passage à instanceof Object[] résolu ce problème.

5
dturanski

getClass().isArray() est nettement plus lent sous Sun Java 5 ou 6 JRE que par IBM).

Tellement que l'utilisation de clazz.getName().charAt(0) == '[' est plus rapide sur Sun JVM.

4
Sebastien Tardif

La réflexion de tableau Java est destinée aux cas où vous ne disposez pas d'une instance de la classe disponible pour faire "instance of" sur. Par exemple, si vous écrivez une sorte de framework d'injection, qui injecte des valeurs dans une nouvelle instance d'une classe, comme le fait JPA, vous devez utiliser la fonctionnalité isArray ().

J'ai blogué à ce sujet plus tôt en décembre. http://blog.adamsbros.org/2010/12/08/Java-array-reflection/

3
Trenton D. Adams

Si vous avez le choix entre une solution réfléchissante et une solution non réfléchissante, ne choisissez jamais la solution réfléchissante (impliquant des objets de classe). Ce n'est pas que ce soit "faux" ou quoi que ce soit, mais tout ce qui implique une réflexion est généralement moins évident et moins clair.

2
Bill K

Il n'y a pas de différence de comportement que je puisse trouver entre les deux (autre que le cas nul évident). Quant à la version à préférer, j'irais avec la seconde. C'est la manière habituelle de faire cela en Java.

Si cela confond les lecteurs de votre code (parce que String[] instanceof Object[] est vrai), vous pouvez utiliser le premier pour être plus explicite si les réviseurs de code continuent à poser des questions à ce sujet.

0
hazzen