¿Cómo ver si un objeto es una matriz sin usar la reflexión?

99

¿Cómo puedo ver en Java si un objeto es una matriz sin usar la reflexión? ¿Y cómo puedo recorrer todos los elementos sin usar la reflexión?

Yo uso Google GWT, así que no puedo usar la reflexión :(

Me encantaría implementar los siguientes métodos sin usar la reflexión:

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

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

Por cierto: tampoco quiero usar JavaScript de manera que pueda usarlo en entornos que no sean GWT.

edbras
fuente

Respuestas:

248

Puedes usar Class.isArray()

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

Esto funciona tanto para matrices de objetos como de tipos primitivos.

Para toString, eche un vistazo Arrays.toString. Deberá verificar el tipo de matriz y llamar al toStringmétodo apropiado .

Steve Kuo
fuente
1
Vale la pena agregar que puede averiguar el tipo de matriz usando obj.getClass().getComponentType().
Steve Chambers
68

Puede utilizar instanceof.

Operador de comparación de tipos JLS 15.20.2 instanceof

 RelationalExpression:
    RelationalExpression instanceof ReferenceType

En tiempo de ejecución, el resultado del instanceofoperador es truesi el valor de RelationalExpression no lo es nully la referencia podría convertirse en ReferenceType sin generar un ClassCastException. De lo contrario, el resultado es false.

Eso significa que puedes hacer algo como esto:

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

Habría que comprobar si el objeto es una instanceof boolean[], byte[], short[], char[], int[], long[], float[], double[], o Object[], si se quiere detectar todos los tipos de matriz.

Además, an int[][]es an instanceof Object[], por lo que, dependiendo de cómo desee manejar las matrices anidadas, puede complicarse.

Para el toString, java.util.Arraystiene una toString(int[])y otras sobrecargas que puede usar. También tiene deepToString(Object[])para matrices anidadas.

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

Va a ser muy repetitivo (pero incluso java.util.Arraysmuy repetitivo ), pero así es en Java con matrices.

Ver también

poligenelubricantes
fuente
Gracias, no se dio cuenta de que es tan simple. Thought insstanceof no se puede utilizar directamente con T [] :(
edbras
2
Por cierto: también noté otra buena forma de descubrir si algo es una matriz Class.isArray () (utilizada en Arrays.deepToString ()).
edbras
@edbras: sí, eso es lo que decía Steve Kuo abajo. Mi solución utiliza una construcción lingüística pura en lugar de una llamada a la API.
polygenelubricants
Funciona bien, solo no uso instanceof sino getClass como comparación. Algo como: if (array.getClass == int []. Class) {Arrays.toString ((int []) array); } Gracias a todos ...
edbras
@edbras: Así es java.util.Arrays, sí. Veo que has estado leyendo el código al que he vinculado.
polygenelubricants
35

Se puede acceder a cada elemento de una matriz por separado usando el siguiente código:

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

Tenga en cuenta que no es necesario saber qué tipo de matriz subyacente es, ya que esto funcionará para cualquier matriz.

user1928596
fuente
2
isArray()ya estaba adecuadamente cubierto en las respuestas publicadas 4 años antes de este.
Jason C
15
Esta respuesta es excelente porque nos muestra cómo obtener el tamaño de una matriz y recuperar un elemento sin conocer su tipo de contenido. Estoy seguro de que la mayoría de la gente nunca antes había escrito un código como este.
Christopher Yang
@MaartenBodewes - Usaría este enlace para decidir qué significa "no usar reflexión" para GWT.
Stephen C
10

No existe una relación de subtipificación entre matrices de tipo primitivo o entre una matriz de un tipo primitivo y una matriz de un tipo de referencia. Consulte JLS 4.10.3 .

Por lo tanto, lo siguiente es incorrecto como prueba para ver si objes una matriz de algún tipo :

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

Específicamente, no funciona si se objtrata de una matriz 1-D de primitivas. (Sin embargo, funciona para matrices primitivas con dimensiones más altas, porque todos los tipos de matrices son subtipos de Object. Pero es discutible en este caso).

Yo uso Google GWT, así que no puedo usar la reflexión :(

La mejor solución (para la isArrayparte de matriz de la pregunta) depende de lo que se considere "usar la reflexión".

  • En GWT, llamar obj.getClass().isArray()no cuenta como usar la reflexión 1 , por lo que es la mejor solución.

  • De lo contrario, la mejor forma de averiguar si un objeto tiene un tipo de matriz es utilizar una secuencia de instanceofexpresiones.

    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[];
    }
  • También puede intentar jugar con el nombre de la clase del objeto de la siguiente manera, pero la llamada a obj.getClass()está al borde de la reflexión.

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

1 - Más precisamente, el Class.isArraymétodo figura como compatible con GWT en esta página .

Stephen C
fuente
0

Puede crear una clase de utilidad para comprobar si la clase representa alguna colección , mapa o matriz

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

Simplemente obj instanceof Object[](probado en JShell).

Sina Madani
fuente