Réflexion de tableau Java: isArray vs instanceof
Y a-t-il une différence de préférence ou de comportement entre l'utilisation de:
if(obj.getClass().isArray()) {}
Et
if(obj instanceof Object[]) {}
?
8 réponses
Dans la plupart des cas, vous devez utiliser l'opérateur instanceof
pour tester si un objet est un tableau.
Généralement, vous testez le type d'un objet avant de passer à un type particulier connu au moment de la compilation. Par exemple, peut-être avez-vous écrit du code qui peut fonctionner avec un Integer[]
ou un int[]
. Vous voulez garder vos lancers 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
se traduit par un code d'octet "instanceof" spécifique, qui est optimisé dans la plupart des JVM application.
Dans des cas plus rares, vous pouvez utiliser la réflexion pour parcourir un graphe d'objet de types inconnus. Dans des cas comme celui-ci, la méthode isArray()
peut être utile car vous ne connaissez pas le type de composant au moment de la compilation; vous pourriez, par exemple, implémenter une sorte de mécanisme de sérialisation et être capable de passer chaque composant du tableau à la même méthode de sérialisation, quel que soit le type.
Il y a deux cas particuliers: références nulles et références à primitive tableau.
Une référence null entraînera instanceof
À résultat false
, tandis que le isArray
jette un NullPointerException
.
Appliqué à un tableau primitif, le instanceof
donne false
sauf si le type de composant de l'opérande de droite correspond exactement au type de Composant. En revanche, {[6] } renvoie true
pour tout type de Composant.
Dans ce dernier cas, si obj est null, vous n'obtiendrez pas une NullPointerException mais un false.
Si {[0] } est de type int[]
disons, alors cela aura un tableau Class
mais ne sera pas une instance de Object[]
. Alors, que voulez-vous faire avec obj
. Si vous allez le lancer, allez avec instanceof
. Si vous allez utiliser la réflexion, utilisez .getClass().isArray()
.
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() ...
Changer en instanceof Object[]
Correction de cela.
getClass().isArray()
est significativement plus lent sur Sun Java 5 ou 6 JRE que sur IBM.
Tellement que l'utilisation de clazz.getName().charAt(0) == '['
est plus rapide sur la JVM Sun.
La réflexion de tableau Java est pour les cas où vous n'avez pas une instance de la classe disponible pour faire "instanceof"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/
Si jamais 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 la réflexion est généralement moins évident et moins clair.
Il n'y a pas de différence de comportement que je peux trouver entre les deux (autre que le cas null évident). Quant à la version à préférer, j'irais avec la seconde. C'est la façon standard de le faire 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.