Como ver se um objeto é um array sem usar reflexão?


99

Como posso ver em Java se um objeto é uma matriz sem usar reflexão? E como posso iterar por todos os itens sem usar reflexão?

Eu uso o Google GWT, portanto, não tenho permissão para usar o reflexo :(

Eu adoraria implementar os seguintes métodos sem usar refelection:

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

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

BTW: nem quero usar JavaScript de forma que possa usá-lo em ambientes não-GWT.

Respostas:


248

Você pode usar Class.isArray()

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

Isso funciona para matrizes de objeto e de tipo primitivo.

Para toString, dê uma olhada em Arrays.toString. Você terá que verificar o tipo de array e chamar o toStringmétodo apropriado .


1
Vale a pena acrescentar que você pode descobrir o tipo de array usando obj.getClass().getComponentType().
— Steve Chambers

68

Você pode usar instanceof.

JLS 15.20.2 Operador de comparação de tipo instanceof

 RelationalExpression:
    RelationalExpression instanceof ReferenceType

Em tempo de execução, o resultado do instanceofoperador é truese o valor de RelationalExpression não for nulle a referência puder ser convertida em ReferenceType sem gerar a ClassCastException. Caso contrário, o resultado é false.

Isso significa que você pode fazer algo assim:

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

Você teria que verificar se o objeto é um instanceof boolean[], byte[], short[], char[], int[], long[], float[], double[], ou Object[], se você quiser detectar todos os tipos de matriz.

Além disso, um int[][]é um instanceof Object[], portanto, dependendo de como você deseja lidar com matrizes aninhadas, pode ficar complicado.

Para o toString, java.util.Arraystem um toString(int[])e outras sobrecargas que você pode usar. Também tem deepToString(Object[])para matrizes aninhadas.

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

Vai ser muito repetitivo (mas até java.util.Arraysé muito repetitivo ), mas é assim em Java com arrays.

Veja também


Obrigado, não sabia que era tão simples. O pensamento insstanceof não poderia ser usado diretamente com T [] :(
— edbras

2
BTW: Eu também notei outra maneira legal de descobrir se algo é um array Class.isArray () (usado em Arrays.deepToString ()).
— edbras

@edbras: sim, é o que Steve Kuo estava dizendo abaixo. Minha solução usa construção linguística pura em vez de chamada de API.
— poligenelubrificantes

Funciona bem, eu só não uso instanceof, mas getClass como comparação. Algo como: if (array.getClass == int []. Class) {Arrays.toString ((int []) array); } Obrigado a todos ..
— edbras

@edbras: É assim que java.util.Arraysfunciona, sim. Vejo que você está lendo o código ao qual vinculei.
— poligenelubrificantes

35

Pode-se acessar cada elemento de uma matriz separadamente usando o seguinte código:

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

Observe que não é necessário saber que tipo de array subjacente é, pois isso funcionará com qualquer array.


2
isArray()já estava adequadamente coberto nas respostas postadas 4 anos antes desta.
— Jason C

15
Essa resposta é ótima porque nos mostra como obter o tamanho de um array e recuperar um elemento sem conhecimento de seu tipo de conteúdo. Tenho certeza de que a maioria das pessoas nunca escreveu um código assim antes.
— Christopher Yang

@MaartenBodewes - Eu usaria este link para decidir o que "não usar reflexão" significa para o GWT.
— Stephen C

10

Não há relacionamento de subtipagem entre matrizes de tipo primitivo ou entre uma matriz de tipo primitivo e matriz de um tipo de referência. Consulte JLS 4.10.3 .

Portanto, o seguinte está incorreto como um teste para ver se objé uma matriz de qualquer tipo :

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

Especificamente, não funciona se objfor uma matriz 1-D de primitivas. (Funciona para matrizes primitivas com dimensões maiores, porque todos os tipos de matrizes são subtipos deObject . Mas é discutível neste caso.)

Eu uso o Google GWT, portanto, não tenho permissão para usar o reflexo :(

A melhor solução (para a isArrayparte da questão da matriz) depende do que conta como "usar reflexão".

  • No GWT, a chamada obj.getClass().isArray()não conta como usar a reflexão 1 , então essa é a melhor solução.

  • Caso contrário, a melhor maneira de descobrir se um objeto tem um tipo de array é usar uma sequência de instanceofexpressões.

    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[];
    }
  • Você também pode tentar mexer com o nome da classe do objeto da seguinte maneira, mas a chamada para obj.getClass()está beirando a reflexão.

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

1 - Mais precisamente, o Class.isArraymétodo é listado como suportado pelo GWT nesta página .


0

Você pode criar uma classe de utilitário para verificar se a classe representa qualquer coleção , mapa ou matriz

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.