Відбиття масиву Java: isArray vs instanceof


177

Чи є різниця в налаштуваннях або поведінці між використанням:

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

і

if(obj instanceof Object[]) {}

?

Відповіді:


203

У більшості випадків вам слід скористатися 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для будь-якого типу компонентів.


7
Так, але скільки різниці це буде робити? Це звучить як мікрооптимізація для мене.
Майкл Майерс

2
@Dims Якщо ви стверджуєте , що obj instanceof int[]врожаї , falseколи ви призначаєте int[]до obj, ви помиляєтеся.
erickson

4
Вибачте, я мав на увазі, що obj instanceof Object[]врожайність falseякщо Object obj = new int[7].
Дімс

3
Правильно, в Java примітивні типи даних не є об'єктами і не поширюються java.lang.Object, так що це має сенс. Але instanceofвсе ще можна використовувати для тестування на примітивні масиви.
erickson

4
-1: Загалом, оскільки примітивні масиви - це масиви, що викликають isArray()слід використовувати. У дуже не загальному випадку, коли лише масиви об'єктів instanceofє альтернативою високої продуктивності.
Сем Харвелл

33

В останньому випадку, якщо obj недійсний, ви отримаєте NullPointerException, але неправдиву.


8

Якщо objє type int[]say, то це буде масив, Classале не буде примірником Object[]. Отже, що ти хочеш робити obj. Якщо ви збираєтеся її відігравати, ідіть з instanceof. Якщо ви збираєтеся використовувати рефлексію, то використовуйте .getClass().isArray().


4

getClass().isArray() на Sun Java 5 або 6 JRE значно повільніше, ніж у IBM.

Настільки, що clazz.getName().charAt(0) == '['швидше використання на Sun JVM.


10
Чи є у вас статистика, тематичне дослідження чи інші докази, з якими ви можете зв’язатись?
Девід Цитрон

4

Нещодавно я зіткнувся з проблемою оновлення програми 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.
kaqqao

3

Відбиття масиву Java - це для випадків, коли у вас немає екземпляра класу для "instanceof". Наприклад, якщо ви пишете якусь рамку ін'єкції, яка вводить значення в новий примірник класу, як, наприклад, JPA, вам потрібно використовувати функцію isArray ().

Я про це блогував раніше у грудні. http://blog.adamsbros.org/2010/12/08/java-array-reflection/


2

Якщо у вас колись є вибір між рефлексивним рішенням і невідбиваючим рішенням, ніколи не вибирайте світловідбиваюче (за участю об'єктів класу). Справа не в тому, що це "Неправильно" чи що-небудь, але все, що включає рефлексію, як правило, менш очевидно і менш зрозуміло.


Е, ну, "instanceof" - це також своєрідне відображення (або, принаймні, самоаналіз), але я розумію вашу думку.
Девід Цитрон

Також, як правило, повільніше.
Божевільний фізик

0

Немає різниці в поведінці, яку я можу знайти між ними (крім очевидного нульового випадку). Щодо того, яку версію віддати перевагу, я б пішов з другою. Це стандартний спосіб зробити це на Java.

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

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