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

99

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

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

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

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

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

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

Edbras
источник

Ответы:

249

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

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

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

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

Стив Куо
источник
1
Стоит добавить, что вы можете узнать тип массива, используя obj.getClass().getComponentType().
Стив Чемберс,
68

Вы можете использовать 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[], если вы хотите , чтобы обнаружить все типы массива.

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

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

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

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

Смотрите также

полигенные смазочные материалы
источник
Спасибо, не понял, что это так просто. Мысль insstanceof не может быть напрямую использована с T [] :(
edbras
2
Кстати: я также заметил еще один хороший способ узнать, является ли что-то массивом Class.isArray () (используется в Arrays.deepToString ()).
edbras
@edbras: да, это то, что Стив Куо говорил внизу. В моем решении вместо вызова API используется чистая лингвистическая конструкция.
polygenelubricants
Он отлично работает, я использую не instanceof, а getClass для сравнения. Что-то вроде: if (array.getClass == int []. Class) {Arrays.toString ((int []) array); } Спасибо всем ..
edbras
@edbras: Вот как java.util.Arraysэто получается, да. Я вижу, что вы читали код, на который я ссылался.
polygenelubricants
35

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

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

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

user1928596
источник
2
isArray()уже был адекватно освещен в ответах, опубликованных за 4 года до этого.
Jason C
15
Этот ответ великолепен, потому что он показывает нам, как получить размер массива и извлечь элемент, не зная его типа содержимого. Я уверен, что большинство людей никогда раньше не писали подобный код.
Кристофер Янг,
@MaartenBodewes - Я бы использовал эту ссылку, чтобы решить, что означает «не использовать отражение» для GWT.
Stephen C
10

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

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

  public static boolean isCollection(Class<?> rawPropertyType) {
        return Collection.class.isAssignableFrom(rawPropertyType) || 
               Map.class.isAssignableFrom(rawPropertyType) || 
               rawPropertyType.isArray();
 }
Лукас Пирес
источник
0

Просто obj instanceof Object[](проверено на JShell).

Сина Мадани
источник