Comment voir si un objet est un tableau sans utiliser la réflexion?

99

Comment puis-je voir en Java si un objet est un tableau sans utiliser la réflexion? Et comment puis-je parcourir tous les éléments sans utiliser la réflexion?

J'utilise Google GWT donc je ne suis pas autorisé à utiliser la réflexion :(

J'aimerais implémenter les méthodes suivantes sans utiliser la refelection:

private boolean isArray(final Object obj) {
  //??..
}

private String toString(final Object arrayObject) {
  //??..
}

BTW: je ne veux pas non plus utiliser JavaScript pour pouvoir l'utiliser dans des environnements non GWT.

edbras
la source

Réponses:

248

Vous pouvez utiliser Class.isArray()

public static boolean isArray(Object obj)
{
    return obj!=null && obj.getClass().isArray();
}

Cela fonctionne pour les tableaux de type objet et primitif.

Pour toString, jetez un œil à Arrays.toString. Vous devrez vérifier le type de tableau et appeler la toStringméthode appropriée .

Steve Kuo
la source
1
Il vaut la peine d'ajouter que vous pouvez trouver le type de tableau en utilisant obj.getClass().getComponentType().
Steve Chambers
68

Vous pouvez utiliser instanceof.

Opérateur de comparaison de types JLS 15.20.2 instanceof

 RelationalExpression:
    RelationalExpression instanceof ReferenceType

Au moment de l'exécution, le résultat de l' instanceofopérateur est truesi la valeur de RelationalExpression n'est pas nullet la référence peut être convertie en ReferenceType sans élever un ClassCastException. Sinon, le résultat est false.

Cela signifie que vous pouvez faire quelque chose comme ceci:

Object o = new int[] { 1,2 };
System.out.println(o instanceof int[]); // prints "true"        

Il faudrait vérifier si l'objet est un instanceof boolean[], byte[], short[], char[], int[], long[], float[], double[]ou Object[], si vous voulez détecter tous les types de tableau.

De plus, an int[][]est un instanceof Object[], donc selon la façon dont vous souhaitez gérer les tableaux imbriqués, cela peut devenir compliqué.

Pour le toString, java.util.Arraysa toString(int[])et d'autres surcharges que vous pouvez utiliser. Il a également deepToString(Object[])pour les tableaux imbriqués.

public String toString(Object arr) {
   if (arr instanceof int[]) {
      return Arrays.toString((int[]) arr);
   } else //...
}

Cela va être très répétitif (mais même java.util.Arraystrès répétitif ), mais c'est comme ça en Java avec des tableaux.

Voir également

lubrifiants polygènes
la source
Merci, il n'a pas réalisé que c'était aussi simple. Pensée insstanceof ne pouvait pas être utilisée directement avec T [] :(
edbras
2
BTW: J'ai également remarqué une autre manière intéressante de découvrir si quelque chose est un tableau Class.isArray () (utilisé dans Arrays.deepToString ()).
edbras
@edbras: oui, c'est ce que disait Steve Kuo en bas. Ma solution utilise une construction linguistique pure au lieu d'un appel API.
polygenelubricants
Cela fonctionne bien, je n'utilise pas seulement instanceof mais getClass comme comparaison. Quelque chose comme: if (array.getClass == int []. Class) {Arrays.toString ((int []) array); } Merci à tous ..
edbras
@edbras: C'est comme java.util.Arraysça, oui. Je vois que vous avez lu le code auquel j'ai lié.
polygenelubricants
35

On peut accéder à chaque élément d'un tableau séparément en utilisant le code suivant:

Object o=...;
if ( o.getClass().isArray() ) {
    for(int i=0; i<Array.getLength(o); i++){
        System.out.println(Array.get(o, i));
    }
}

Notez qu'il n'est pas nécessaire de savoir de quel type de tableau sous-jacent il s'agit, car cela fonctionnera pour n'importe quel tableau.

user1928596
la source
2
isArray()était déjà suffisamment couverte dans les réponses publiées 4 ans avant celle-ci.
Jason C
15
Cette réponse est excellente car elle nous montre comment obtenir la taille d'un tableau et récupérer un élément sans connaître son type de contenu. Je suis sûr que la plupart des gens n'ont jamais écrit de code comme celui-ci auparavant.
Christopher Yang
@MaartenBodewes - J'utiliserais ce lien pour décider de ce que «ne pas utiliser de réflexion» signifie pour GWT.
Stephen C
10

Il n'y a pas de relation de sous-typage entre les tableaux de type primitif, ou entre un tableau d'un type primitif et un tableau d'un type référence. Voir JLS 4.10.3 .

Par conséquent, ce qui suit est incorrect en tant que test pour voir s'il objs'agit d'un tableau de n'importe quel type :

// INCORRECT!
public boolean isArray(final Object obj) {
    return obj instanceof Object[];
}

Plus précisément, cela ne fonctionne pas s'il objs'agit d'un tableau 1-D de primitives. (Cela fonctionne pour les tableaux primitifs avec des dimensions plus élevées, car tous les types de tableaux sont des sous-types de Object. Mais c'est sans intérêt dans ce cas.)

J'utilise Google GWT donc je ne suis pas autorisé à utiliser la réflexion :(

La meilleure solution (pour la isArraypartie tableau de la question) dépend de ce qui compte comme "utiliser la réflexion".

  • Dans GWT, l'appel obj.getClass().isArray()ne compte pas comme l'utilisation de la réflexion 1 , c'est donc la meilleure solution.

  • Sinon, la meilleure façon de déterminer si un objet a un type de tableau est d'utiliser une séquence d' instanceofexpressions.

    public boolean isArray(final Object obj) {
        return obj instanceof Object[] || obj instanceof boolean[] ||
           obj instanceof byte[] || obj instanceof short[] ||
           obj instanceof char[] || obj instanceof int[] ||
           obj instanceof long[] || obj instanceof float[] ||
           obj instanceof double[];
    }
    
  • Vous pouvez également essayer de jouer avec le nom de la classe de l'objet comme suit, mais l'appel à obj.getClass()est à la limite de la réflexion.

    public boolean isArray(final Object obj) {
        return obj.getClass().toString().charAt(0) == '[';
    }
    

1 - Plus précisément, la Class.isArrayméthode est répertoriée comme prise en charge par GWT dans cette page .

Stephen C
la source
0

Vous pouvez créer une classe utilitaire pour vérifier si la classe représente une collection , une carte ou un tableau

  public static boolean isCollection(Class<?> rawPropertyType) {
        return Collection.class.isAssignableFrom(rawPropertyType) || 
               Map.class.isAssignableFrom(rawPropertyType) || 
               rawPropertyType.isArray();
 }
Lucas Pires
la source
0

Simplement obj instanceof Object[](testé sur JShell).

Sina Madani
la source