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[]) {}
?
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[]) {}
?
Réponses:
Dans la plupart des cas, vous devez utiliser le instanceof
opérateur pour tester si un objet est un tableau.
En règle générale, vous testez le type d'un objet avant le downcasting vers un type particulier qui est connu au moment de la compilation. Par exemple, vous avez peut-être écrit du code qui peut fonctionner avec un Integer[]
ou un int[]
. Vous voudriez 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 JVM, l' instanceof
opérateur se traduit par une "instanceof" spécifique octet de code , optimisé dans la plupart des implémentations JVM.
Dans des cas plus rares, vous pouvez utiliser la réflexion pour parcourir un graphe d'objets de types inconnus. Dans des cas comme celui-ci, leisArray()
méthode 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 son type.
Il existe deux cas particuliers: les références nulles et les références aux tableaux primitifs.
Une référence nulle entraînera instanceof
le résultat false
, tandis que le isArray
jette unNullPointerException
.
Appliqué à un tableau primitif, le instanceof
rendement donne à false
moins que le type de composant sur l'opérande de droite corresponde exactement au type de composant. En revanche, isArray()
retournera true
pour tout type de composant.
obj instanceof int[]
cède false
lorsque vous attribuez un int[]
à obj
, vous vous trompez.
obj instanceof Object[]
cède false
si Object obj = new int[7]
.
java.lang.Object
, donc cela a du sens. Mais instanceof
peut toujours être utilisé pour tester les tableaux primitifs.
isArray()
il faut utiliser. Dans le cas particulier très peu général de n'avoir que des tableaux d'objets, instanceof
fournit une alternative de haute performance.
Si obj
est de type, int[]
disons, alors cela aura un tableau Class
mais pas une instance de Object[]
. Alors, que voulez-vous faire obj
. Si vous voulez le lancer, allez-y instanceof
. Si vous comptez utiliser la réflexion, utilisez .getClass().isArray()
.
getClass().isArray()
est nettement plus lent sur Sun Java 5 ou 6 JRE que sur IBM.
À tel point que l'utilisation clazz.getName().charAt(0) == '['
est plus rapide sur Sun JVM.
J'ai récemment rencontré un problème lors de la mise à niveau d'une application Groovy du JDK 5 au JDK 6. L'utilisation a isArray()
échoué dans JDK6:
MissingMethodException:
No signature of sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl.isArray() ...
Changer pour instanceof Object[]
résoudre ce problème.
isArray
est une méthode de Class
, non Type
, donc bien sûr GenericArrayTypeImpl
n'a pas cette méthode. Et getClass
vous ne pouvez jamais retourner un non- Class
Type
, donc vous (ou Groovy ??) devez avoir fait quelque chose de mal pour obtenir cela, comme en supposant que tout Type
est un Class
.
La réflexion de tableau Java est pour les cas où vous n'avez pas d'instance de la classe disponible pour faire "instanceof". 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 une réflexion est généralement moins évident et moins clair.
Il n'y a aucune 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 standard de faire cela en Java.
Si cela déroute les lecteurs de votre code (parce que String[] instanceof Object[]
c'est vrai), vous pouvez utiliser le premier pour être plus explicite si les réviseurs de code continuent de vous poser des questions à ce sujet.