Чи є різниця в налаштуваннях або поведінці між використанням:
if(obj.getClass().isArray()) {}
і
if(obj instanceof Object[]) {}
?
Чи є різниця в налаштуваннях або поведінці між використанням:
if(obj.getClass().isArray()) {}
і
if(obj instanceof Object[]) {}
?
Відповіді:
У більшості випадків вам слід скористатися instanceof
оператором, щоб перевірити, чи є об’єкт масивом.
Як правило, ви перевіряєте тип об'єкта перед тим, як спустити на конкретний тип, який відомий під час компіляції. Наприклад, можливо, ви написали якийсь код, який може працювати з a Integer[]
чи an 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
є type int[]
say, то це буде масив, 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
, тож ти (або Гроовий ??) повинен був зробити щось не так, якби припустити, що кожен Type
є Class
.
Відбиття масиву Java - це для випадків, коли у вас немає екземпляра класу для "instanceof". Наприклад, якщо ви пишете якусь рамку ін'єкції, яка вводить значення в новий примірник класу, як, наприклад, JPA, вам потрібно використовувати функцію isArray ().
Я про це блогував раніше у грудні. http://blog.adamsbros.org/2010/12/08/java-array-reflection/
Якщо у вас колись є вибір між рефлексивним рішенням і невідбиваючим рішенням, ніколи не вибирайте світловідбиваюче (за участю об'єктів класу). Справа не в тому, що це "Неправильно" чи що-небудь, але все, що включає рефлексію, як правило, менш очевидно і менш зрозуміло.
Немає різниці в поведінці, яку я можу знайти між ними (крім очевидного нульового випадку). Щодо того, яку версію віддати перевагу, я б пішов з другою. Це стандартний спосіб зробити це на Java.
Якщо це бентежить читачів вашого коду (тому що String[] instanceof Object[]
це правда), ви можете скористатися першим, щоб бути більш чітким, якщо рецензенти коду продовжують запитувати про це.