Wie kann man sehen, ob ein Objekt ein Array ist, ohne Reflexion zu verwenden?

98

Wie kann ich in Java sehen, ob ein Objekt ein Array ist, ohne Reflektion zu verwenden? Und wie kann ich alle Elemente ohne Reflexion durchlaufen?

Ich verwende Google GWT, daher darf ich keine Reflektion verwenden :(

Ich würde gerne die folgenden Methoden implementieren, ohne die Neuauswahl zu verwenden:

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

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

Übrigens: Ich möchte JavaScript auch nicht so verwenden, dass ich es in Nicht-GWT-Umgebungen verwenden kann.

edbras
quelle

Antworten:

247

Sie können verwenden Class.isArray()

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

Dies funktioniert sowohl für Objekt- als auch für primitive Arrays.

Für toString werfen Sie einen Blick auf Arrays.toString. Sie müssen den Array-Typ überprüfen und die entsprechende toStringMethode aufrufen .

Steve Kuo
quelle
1
Es lohnt sich hinzuzufügen, dass Sie den Array-Typ mithilfe von herausfinden können obj.getClass().getComponentType().
Steve Chambers
68

Sie können verwenden instanceof.

JLS 15.20.2 Typvergleichsoperator instanceof

 RelationalExpression:
    RelationalExpression instanceof ReferenceType

Zur Laufzeit ist das Ergebnis des instanceofOperators, truewenn der Wert von RelationalExpression nicht lautet nullund die Referenz in den ReferenceType umgewandelt werden kann, ohne a auszulösen ClassCastException. Ansonsten ist das Ergebnis false.

Das heißt, Sie können so etwas tun:

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

Sie müßten überprüfen , ob das Objekt ein instanceof boolean[], byte[], short[], char[], int[], long[], float[], double[], oder Object[], wenn Sie alle Array - Typen erkannt werden sollen.

Außerdem int[][]ist an ein instanceof Object[]. Je nachdem, wie Sie mit verschachtelten Arrays umgehen möchten, kann dies kompliziert werden.

Für die toString, java.util.Arrayshat eine toString(int[])und andere Überlastungen Sie verwenden können. Es hat auch deepToString(Object[])für verschachtelte Arrays.

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

Es wird sich sehr wiederholen (aber es wird sich auch java.util.Arrayssehr wiederholen ), aber so ist es in Java mit Arrays.

Siehe auch

Polygenschmierstoffe
quelle
Danke, es war nicht klar, dass es so einfach ist. Gedanken Insofanceof konnte nicht einfach mit T [] :(
edbras
2
Übrigens: Mir ist auch eine andere gute Möglichkeit aufgefallen, herauszufinden, ob es sich bei einem Array um ein Array handelt. Class.isArray () (wird in Arrays.deepToString () verwendet).
Edbras
@edbras: Ja, das hat Steve Kuo unten gesagt. Meine Lösung verwendet ein reines Sprachkonstrukt anstelle eines API-Aufrufs.
Polygenelubricants
Es funktioniert gut, ich verwende nur keine Instanz von, sondern getClass als Vergleich. So etwas wie: if (array.getClass == int []. Class) {Arrays.toString ((int []) array); } Vielen Dank an alle ..
Edbras
@edbras: So java.util.Arraysgeht das ja. Ich sehe, dass Sie den Code gelesen haben, mit dem ich verlinkt habe.
Polygenelubricants
35

Mit dem folgenden Code kann auf jedes Element eines Arrays separat zugegriffen werden:

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

Beachten Sie, dass Sie nicht wissen müssen, um welche Art von zugrunde liegendem Array es sich handelt, da dies für jedes Array funktioniert.

user1928596
quelle
2
isArray()wurde bereits 4 Jahre zuvor angemessen in den Antworten behandelt.
Jason C
15
Diese Antwort ist großartig, weil sie uns zeigt, wie man die Größe eines Arrays ermittelt und ein Element ohne Kenntnis seines Inhaltstyps abruft. Ich bin sicher, dass die meisten Leute noch nie so einen Code geschrieben haben.
Christopher Yang
@ MaartenBodewes - Ich würde diesen Link verwenden , um zu entscheiden, was "keine Reflexion verwenden" für GWT bedeutet.
Stephen C
10

Es gibt keine Subtypisierungsbeziehung zwischen Arrays vom primitiven Typ oder zwischen einem Array eines primitiven Typs und einem Array eines Referenztyps. Siehe JLS 4.10.3 .

Daher ist Folgendes als Test falsch, um festzustellen, ob objes sich um ein Array jeglicher Art handelt :

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

Insbesondere funktioniert es nicht, wenn objes sich um ein 1-D-Array von Grundelementen handelt. (Es funktioniert jedoch für primitive Arrays mit höheren Dimensionen, da alle Array-Typen Untertypen von sind Object. In diesem Fall ist dies jedoch umstritten.)

Ich verwende Google GWT, daher darf ich keine Reflektion verwenden :(

Die beste Lösung (für den isArrayArray-Teil der Frage) hängt davon ab, was als "Verwenden von Reflexion" gilt.

  • In GWT zählt das Aufrufen obj.getClass().isArray()nicht als Verwendung von Reflection 1 , daher ist dies die beste Lösung.

  • Andernfalls können Sie am besten herausfinden, ob ein Objekt einen Array-Typ hat, instanceofindem Sie eine Folge von Ausdrücken verwenden.

    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[];
    }
  • Sie können auch versuchen, mit dem Namen der Objektklasse wie folgt herumzuspielen, aber der Aufruf von obj.getClass()grenzt an Reflexion.

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

1 - Genauer gesagt wird die Class.isArrayMethode auf dieser Seite als von GWT unterstützt aufgeführt .

Stephen C.
quelle
0

Sie können eine Dienstprogrammklasse erstellen, um zu überprüfen, ob die Klasse eine Sammlung , eine Zuordnung oder ein Array darstellt

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

Einfach obj instanceof Object[](auf JShell getestet).

Sina Madani
quelle