Как определить, является ли объект массивом без использования отражения?

Как я могу видеть на Java, если объект представляет собой массив без использования отражения? И как я могу перебирать все элементы без отражения?

Я использую Google GWT, поэтому мне не разрешено использовать рефлексию: (

Мне бы хотелось реализовать следующие методы без использования refelection:

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

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

Кстати: и я не хочу использовать JavaScript, чтобы я мог использовать его в средах без GWT.

Ответ 1

Вы можете использовать Class.isArray()

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

Это работает как для массивов объектов, так и для примитивных типов.

Для toString взгляните на Arrays.toString. Вам нужно будет проверить тип массива и вызвать соответствующий метод toString.

Ответ 2

Вы можете использовать instanceof.

JLS 15.20.2 Оператор сравнения типов instanceof

 RelationalExpression:
    RelationalExpression instanceof ReferenceType

Во время выполнения результат оператора instanceof равен true, если значение RelationalExpression не равно null, и ссылка может быть передана в ReferenceType без повышения a ClassCastException. В противном случае результат false.

Это означает, что вы можете сделать что-то вроде этого:

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

Вам нужно будет проверить, есть ли объект instanceof boolean[], byte[], short[], char[], int[], long[], float[], double[] или Object[], если вы хотите определить все типы массивов.

Кроме того, int[][] является instanceof Object[], поэтому в зависимости от того, как вы хотите обрабатывать вложенные массивы, он может усложняться.

Для toString java.util.Arrays имеет toString(int[]) и другие перегрузки, которые вы можете использовать. Он также имеет deepToString(Object[]) для вложенных массивов.

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

Это будет очень повторяющимся (но даже java.util.Arrays очень повторяется), но так, как в Java с массивами.

См. также

Ответ 3

Можно получить доступ к каждому элементу массива отдельно, используя следующий код:

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

Обратите внимание, что нет необходимости знать, какой он базовый массив, поскольку это будет работать для любого массива.

Ответ 4

Не существует отношения подтипов между массивами примитивного типа или между массивом примитивного типа и массивом ссылочного типа. См. JLS 4.10.3.

Поэтому в качестве теста ниже показано, является ли obj массивом любого вида:

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

В частности, он не работает, если obj является одномерным массивом примитивов. (Это работает для примитивных массивов с более высокими измерениями, потому что все типы массивов являются подтипами Object. Но в данном случае это спорный вопрос.)

Я использую Google GWT, поэтому мне запрещено использовать отражение :(

Лучшее решение (часть вопроса о массиве isArray) зависит от того, что считать "использованием отражения".

  • В GWT вызов obj.getClass().isArray() не считается использованием отражения 1 так что это лучшее решение.

  • В противном случае лучший способ выяснить, имеет ли объект тип массива, - это использовать последовательность выражений instanceof.

    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[];
    }
    
  • Вы также можете попробовать поиграть с именем класса объекта следующим образом, но вызов obj.getClass() граничит с отражением.

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

1 - Точнее, метод Class.isArray указан как поддерживаемый GWT на этой странице.

Ответ 5

Вы можете создать служебный класс, чтобы проверить, представляет ли класс какую-либо коллекцию, карту или массив

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