Як зрозуміти, чи об’єкт є масивом, не використовуючи відображення?


99

Як я бачу в Java, якщо Об'єкт є масивом без використання відображення? І як я можу повторити всі предмети, не використовуючи рефлексію?

Я використовую Google GWT, тому мені не дозволяється використовувати відображення :(

Я хотів би реалізувати такі методи, не використовуючи рефлексію:

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

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

BTW: ні я не хочу використовувати JavaScript таким, щоб я міг його використовувати в не-GWT середовищах.

Відповіді:


248

Можна використовувати 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 без підвищення 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[], якщо ви хочете , щоб виявити всі типи масиву.

Крім того, an 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 з масивами.

Дивитися також


Дякую, він не зрозумів, що це так просто. Думка про неможливість використання прямо з T [] :(
edbras

2
BTW: Я також помітив ще один приємний спосіб виявити, чи є щось масивом Class.isArray () (використовується в Arrays.deepToString ()).
edbras

@edbras: так, саме так говорив Стів Куо нижче. Моє рішення використовує чисто лінгвістичну конструкцію замість виклику API.
полігенмастильні матеріали

Це добре працює, я не використовую лише instanceof, але getClass як порівняння. Щось на зразок: if (array.getClass == int []. Class) {Arrays.toString ((int []) масив); } Дякую всім ..
edbras

@edbras: Ось як java.util.Arraysце відбувається, так. Я бачу, що ви читали код, з яким я пов’язаний.
полігенмастильні матеріали

35

Можна отримати доступ до кожного елемента масиву окремо за допомогою наступного коду:

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

Зауважте, що непотрібно знати, що це за базовий масив, оскільки це буде працювати для будь-якого масиву.


2
isArray()вже було адекватно висвітлено у відповідях, опублікованих за 4 роки до цього.
Джейсон C

15
Ця відповідь чудова, тому що вона показує нам, як отримати розмір масиву та отримати елемент, не знаючи його типу вмісту. Я впевнений, що більшість людей ніколи раніше не писали подібний код.
Крістофер Ян

@MaartenBodewes - Я б скористався цим посиланням, щоб вирішити, що означає "не використання рефлексії" для GWT.
Стівен С

10

Не існує взаємозв'язку підтипів між масивами примітивного типу або між масивом примітивного типу та масивом еталонного типу. Див. JLS 4.10.3 .

Отже, наведене нижче тест є невірним як тест, щоб визначити, чи objє масив будь-якого виду :

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

Зокрема, він не працює, якщо objє 1-D масив примітивів. (Це працює для примітивних масивів з більшими розмірами, оскільки всі типи масивів є підтипами 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();
 }

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.