Come vedere se un oggetto è un array senza usare la riflessione?


99

Come posso vedere in Java se un oggetto è un array senza usare la riflessione? E come posso scorrere tutti gli elementi senza utilizzare la riflessione?

Uso Google GWT quindi non sono autorizzato a utilizzare la riflessione :(

Mi piacerebbe implementare i seguenti metodi senza utilizzare la selezione:

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

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

BTW: nemmeno voglio usare JavaScript in modo da poterlo usare in ambienti non GWT.

Risposte:


248

Puoi usare Class.isArray()

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

Funziona sia per gli array di oggetti che per quelli di tipo primitivo.

Per toString dai un'occhiata a Arrays.toString. Dovrai controllare il tipo di array e chiamare il toStringmetodo appropriato .


1
Vale la pena aggiungere che puoi scoprire il tipo di array usando obj.getClass().getComponentType().
Steve Chambers

68

Puoi usare instanceof.

JLS 15.20.2 Operatore di confronto dei tipi instanceof

 RelationalExpression:
    RelationalExpression instanceof ReferenceType

In fase di esecuzione, il risultato instanceofdell'operatore è truese il valore di RelationalExpression non è nulle il riferimento potrebbe essere sottoposto a cast a ReferenceType senza sollevare a ClassCastException. Altrimenti il ​​risultato è false.

Ciò significa che puoi fare qualcosa del genere:

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

Dovreste controllare se l'oggetto è un instanceof boolean[], byte[], short[], char[], int[], long[], float[], double[], o Object[], se si vuole rilevare tutti i tipi di array.

Inoltre, an int[][]è an instanceof Object[], quindi a seconda di come si desidera gestire gli array annidati, può diventare complicato.

Per il toString, java.util.Arraysha a toString(int[])e altri sovraccarichi che puoi usare. Ha anche deepToString(Object[])per gli array annidati.

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

Sarà molto ripetitivo (ma anche java.util.Arraysmolto ripetitivo ), ma è così in Java con gli array.

Guarda anche


Grazie, non si è reso conto che è così semplice. Il pensiero insstanceof non può essere usato direttamente con T [] :(
edbras

2
BTW: ho anche notato un altro bel modo per scoprire se qualcosa è un array Class.isArray () (usato in Arrays.deepToString ()).
edbras

@edbras: sì, è quello che diceva Steve Kuo in basso. La mia soluzione utilizza un costrutto linguistico puro invece della chiamata API.
lubrificanti poligenici

Funziona bene, solo non uso instanceof ma getClass come confronto. Qualcosa come: if (array.getClass == int []. Class) {Arrays.toString ((int []) array); } Grazie a tutti ..
edbras

@edbras: Ecco come java.util.Arraysfunziona, sì. Vedo che hai letto il codice a cui mi sono collegato.
lubrificanti poligenici

35

È possibile accedere separatamente a ciascun elemento di un array utilizzando il codice seguente:

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

Si noti che non è necessario sapere che tipo di array sottostante è, poiché funzionerà per qualsiasi array.


2
isArray()era già adeguatamente trattato nelle risposte pubblicate 4 anni prima di questa.
Jason C

15
Questa risposta è ottima perché ci mostra come ottenere la dimensione di un array e recuperare un elemento senza conoscere il suo tipo di contenuto. Sono sicuro che la maggior parte delle persone non ha mai scritto un codice come questo prima.
Christopher Yang

@MaartenBodewes - Vorrei utilizzare questo collegamento per decidere cosa significa "non usare la riflessione" per GWT.
Stephen C

10

Non esiste alcuna relazione di sottotipizzazione tra array di tipo primitivo o tra un array di un tipo primitivo e un array di un tipo di riferimento. Vedere JLS 4.10.3 .

Pertanto, quanto segue non è corretto come test per vedere se objè un array di qualsiasi tipo :

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

In particolare, non funziona se objè un array 1-D di primitive. (Funziona per array primitivi con dimensioni maggiori, perché tutti i tipi di array sono sottotipi di Object. Ma in questo caso è discutibile.)

Uso Google GWT quindi non sono autorizzato a utilizzare la riflessione :(

La soluzione migliore (per la isArrayparte di matrice della domanda) dipende da ciò che conta come "usare la riflessione".

  • In GWT, la chiamata obj.getClass().isArray()non conta come utilizzare la riflessione 1 , quindi questa è la soluzione migliore.

  • Altrimenti, il modo migliore per capire se un oggetto ha un tipo di matrice è usare una sequenza di instanceofespressioni.

    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[];
    }
  • Potresti anche provare a scherzare con il nome della classe dell'oggetto come segue, ma la chiamata a obj.getClass()rasenta la riflessione.

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

1 - Più precisamente, il Class.isArraymetodo è elencato come supportato da GWT in questa pagina .


0

È possibile creare una classe di utilità per verificare se la classe rappresenta una raccolta , una mappa o una matrice

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.