Отражение массива Java: isArray против instanceof - PullRequest
170 голосов
/ 21 октября 2008

Есть ли предпочтения или различия в поведении между использованием:

if(obj.getClass().isArray()) {}

и

if(obj instanceof Object[]) {}

Ответы [ 8 ]

198 голосов
/ 21 октября 2008

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

Как правило, вы проверяете тип объекта, прежде чем переходить к определенному типу, который известен во время компиляции. Например, возможно, вы написали некоторый код, который может работать с Integer[] или int[]. Вы бы хотели охранять свои заклинания с помощью instanceof:

if (obj instanceof Integer[]) {
    Integer[] array = (Integer[]) obj;
    /* Use the boxed array */
} else if (obj instanceof int[]) {
    int[] array = (int[]) obj;
    /* Use the primitive array */
} else ...

На уровне JVM оператор instanceof преобразуется в определенный "instanceof" байт-код, который оптимизирован в большинстве реализаций JVM.

В более редких случаях вы можете использовать отражение для обхода графа объектов неизвестных типов. В подобных случаях метод isArray() может быть полезен, потому что вы не знаете тип компонента во время компиляции; вы можете, например, реализовать какой-то механизм сериализации и иметь возможность передавать каждый компонент массива к одному и тому же методу сериализации, независимо от типа.

Существует два особых случая: нулевые ссылки и ссылки на примитивные массивы.

Нулевая ссылка приведет к instanceof для результата false, в то время как isArray выдает NullPointerException.

Применительно к массиву примитивов instanceof дает false, если тип компонента в правом операнде точно не соответствует типу компонента. Напротив, isArray() вернет true для любого типа компонента.

32 голосов
/ 21 октября 2008

В последнем случае, если значение obj равно нулю, вы получите не NullPointerException, а false.

8 голосов
/ 21 октября 2008

Если obj имеет тип int[] скажем, тогда он будет иметь массив Class, но не будет экземпляром Object[]. Итак, что вы хотите сделать с obj. Если вы собираетесь разыграть его, используйте instanceof. Если вы собираетесь использовать отражение, тогда используйте .getClass().isArray().

5 голосов
/ 13 октября 2012

Недавно я столкнулся с проблемой обновления приложения Groovy с JDK 5 до JDK 6. Не удалось использовать isArray() в JDK6:

MissingMethodException:
No signature of sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl.isArray() ...

Изменение на instanceof Object[] исправило это.

4 голосов
/ 05 ноября 2009

getClass().isArray() значительно медленнее в Sun Java 5 или 6 JRE, чем в IBM.

Настолько, что использование clazz.getName().charAt(0) == '[' быстрее в Sun JVM.

3 голосов
/ 01 января 2011

Отражение массива Java предназначено для случаев, когда у вас нет экземпляра класса, доступного для выполнения instanceof. Например, если вы пишете какой-то каркас внедрения, который внедряет значения в новый экземпляр класса, такой как JPA, то вам нужно использовать функцию isArray ().

Я писал об этом в начале декабря. http://blog.adamsbros.org/2010/12/08/java-array-reflection/

2 голосов
/ 21 октября 2008

Если у вас когда-либо есть выбор между отражающим решением и неотражающим решением, никогда не выбирайте отражающее решение (с объектами класса). Дело не в том, что это «неправильно» или что-то в этом роде, но все, что связано с отражением, обычно менее очевидно и менее ясно.

0 голосов
/ 21 октября 2008

Нет никакой разницы в поведении, которое я могу найти между этими двумя (кроме очевидного нулевого случая). Что касается какой версии отдать предпочтение, я бы пошел со второй. Это стандартный способ сделать это в Java.

Если это смущает читателей вашего кода (потому что String[] instanceof Object[] - это правда), вы можете использовать первое, чтобы быть более явным, если рецензенты кода продолжают спрашивать об этом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...