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.

Edbras
fonte

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 .

Steve Kuo
fonte
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

poligenelubrificantes
fonte
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.

user1928596
fonte
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 .

Stephen C
fonte
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();
 }
Lucas pires
fonte
0

Simplesmente obj instanceof Object[](testado em JShell).

Sina Madani
fonte