Как посмотреть, является ли объект массивом без использования отражения? - PullRequest
87 голосов
/ 28 апреля 2010

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

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

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

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

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

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

Ответы [ 5 ]

224 голосов
/ 28 апреля 2010

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

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

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

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

64 голосов
/ 28 апреля 2010

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

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

 RelationalExpression:
    RelationalExpression instanceof ReferenceType

Во время выполнения результат оператора instanceof равен true, если значение RelationalExpression не равно null и ссылка может быть приведена к ReferenceType без поднятия 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 с массивами.

Смотри также

30 голосов
/ 09 мая 2014

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

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

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

9 голосов
/ 28 апреля 2010

Нет связи подтипов между массивами примитивного типа или между массивом примитивного типа и массивом ссылочного типа. См. 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 на этой странице .

0 голосов
/ 22 января 2019

Можно создать служебный класс, чтобы проверить, представляет ли этот класс Коллекция , Карта или Массив

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