Есть ли предпочтения или различия в поведении между использованием:
if(obj.getClass().isArray()) {}
и
if(obj instanceof Object[]) {}
?
Есть ли предпочтения или различия в поведении между использованием:
if(obj.getClass().isArray()) {}
и
if(obj instanceof Object[]) {}
?
Ответы:
В большинстве случаев вы должны использовать 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
выбрасывает a NullPointerException
.
Применительно к примитивному массиву instanceof
выдает результат, false
если только тип компонента в правом операнде точно не соответствует типу компонента. Напротив, isArray()
вернется true
для любого типа компонента.
obj instanceof int[]
урожаи , false
когда вы назначаете int[]
к obj
, вы ошибаетесь.
obj instanceof Object[]
дает, false
если Object obj = new int[7]
.
java.lang.Object
, так что это имеет смысл. Но instanceof
все еще может использоваться для проверки примитивных массивов.
isArray()
следует использовать вызовы . В очень не общем частном случае наличия только массивов объектов instanceof
обеспечивает высокую производительность альтернативы.
Если obj
имеет тип int[]
сказать, то это будет иметь массив, Class
но не будет экземпляром Object[]
. Итак, что вы хотите сделать с obj
. Если вы собираетесь разыграть его, продолжайте instanceof
. Если вы собираетесь использовать отражение, тогда используйте .getClass().isArray()
.
getClass().isArray()
значительно медленнее в Sun Java 5 или 6 JRE, чем в IBM.
Настолько, что использование clazz.getName().charAt(0) == '['
быстрее на Sun JVM.
Недавно я столкнулся с проблемой при обновлении приложения Groovy с JDK 5 до JDK 6. Не isArray()
удалось использовать в JDK6:
MissingMethodException:
No signature of sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl.isArray() ...
Меняется, чтобы instanceof Object[]
исправить это.
isArray
это метод Class
, нет Type
, поэтому, конечно GenericArrayTypeImpl
, не имеет этот метод. И getClass
никогда не сможет вернуть не- Class
Type
, так что вы (или Groovy ??), должно быть, сделали что-то не так, чтобы получить это, например, предположив, что каждый Type
- это Class
.
Отражение массива Java предназначено для случаев, когда у вас нет экземпляра Class, доступного для выполнения instanceof. Например, если вы пишете какую-то инфраструктуру внедрения, которая внедряет значения в новый экземпляр класса, такой как JPA, то вам нужно использовать функциональность isArray ().
Я писал об этом в начале декабря. http://blog.adamsbros.org/2010/12/08/java-array-reflection/
Если у вас когда-либо есть выбор между отражающим решением и неотражающим решением, никогда не выбирайте отражающее решение (включая объекты класса). Дело не в том, что это «неправильно» или что-то в этом роде, но все, что связано с отражением, обычно менее очевидно и менее ясно.
Нет никакой разницы в поведении, которое я могу найти между этими двумя (кроме очевидного нулевого случая). Что касается какой версии отдать предпочтение, я бы пошел со второй. Это стандартный способ сделать это в Java.
Если это смущает читателей вашего кода (потому что String[] instanceof Object[]
это правда), вы можете использовать первое, чтобы быть более явным, если рецензенты кода продолжают спрашивать об этом.