Что из следующего лучше?
a instanceof B
или
B.class.isAssignableFrom(a.getClass())
Единственное различие, о котором я знаю, состоит в том, что когда 'a' равно нулю, первое возвращает false, а второе выдает исключение. Кроме этого, они всегда дают один и тот же результат?
java
instanceof
reflection
Megamug
источник
источник
Ответы:
При использовании
instanceof
вам нужно знать классB
во время компиляции. При использованииisAssignableFrom()
он может быть динамическим и меняться во время выполнения.источник
a instanceof Bref.getClass()
. как это может быть принятым ответом с таким небольшим количеством объяснений (или его отсутствием)?a instanceof Bref
нетa instanceof Bref.class
. Второй аргумент оператора instanceof - это имя класса, а не выражение, разрешающее экземпляр объекта класса.B.class.isAssignableFrom(a.getClass())
, B известен, иa instanceof B
лучше. Правильно?instanceof
может использоваться только со ссылочными типами, но не примитивными.isAssignableFrom()
может использоваться с объектами любого класса:Видеть http://java.sun.com/javase/6/docs/api/java/lang/Class.html#isAssignableFrom(java.lang.Class) .
источник
Говоря с точки зрения производительности:
TL; DR
Используйте isInstance или instanceof, которые имеют аналогичную производительность. isAssignableFrom немного медленнее.
Сортировка по производительности:
На основе эталона 2000 итераций на JAVA 8 для Windows x64 с 20 итерациями прогрева.
В теории
Используя программный просмотрщик байт-кода, мы можем перевести каждый оператор в байт-код.
В контексте:
ЯВА:
Bytecode:
ЯВА:
Bytecode:
ЯВА:
Bytecode:
Измеряя, сколько инструкций байт-кода используется каждым оператором, мы можем ожидать, что instanceof и isInstance будут быстрее, чем isAssignableFrom . Однако фактическая производительность определяется не байт-кодом, а машинным кодом (который зависит от платформы). Давайте сделаем микро-тест для каждого из операторов.
Эталон
Предоставлено: как советует @ aleksandr-dubinsky, и спасибо @yura за предоставление базового кода, вот эталонный тест JMH (см. Это руководство по настройке ):
Дали следующие результаты (оценка - это количество операций в единицу времени , поэтому чем выше оценка, тем лучше):
Предупреждение
instanceof
в контексте вашего кода может быть оптимизирован легче, чем,isInstance
например, ...Чтобы дать вам пример, возьмите следующий цикл:
Благодаря JIT код оптимизируется в какой-то момент, и мы получаем:
Запись
Первоначально эта статья делала свой собственный тест с использованием цикла for в сыром JAVA, который дал ненадежные результаты, так как некоторые оптимизации, такие как Just In Time, могут устранить цикл. Так что в основном измерения , сколько времени сделал взятие JIT компилятор для оптимизации цикла: см тест производительности зависит от числа итераций для получения более подробной информации
Смежные вопросы
источник
instanceof
это байт-код, который использует, по сути, ту же логику, что иcheckcast
(байт-код за преобразованием). Это будет по своей природе быстрее, чем другие варианты, независимо от степени оптимизации JITC.isAssignableFrom()
является динамичным.Более прямым эквивалентом
a instanceof B
являетсяЭто работает (возвращает ложь) , если
a
этоnull
слишком.источник
Помимо основных различий, упомянутых выше, есть существенная тонкая разница между оператором instanceof и методом isAssignableFrom в Class.
Читайте
instanceof
как «это (левая часть) экземпляр этого или любого подкласса этого (правая часть)» и читайтеx.getClass().isAssignableFrom(Y.class)
как «Могу ли я написатьX x = new Y()
». Другими словами, оператор instanceof проверяет, является ли левый объект тем же или подклассом правого класса, в то время какisAssignableFrom
проверяет, можем ли мы присвоить объект класса параметра (from) ссылке на класс, для которого вызывается метод.Обратите внимание, что оба они рассматривают фактический экземпляр, а не ссылочный тип.
Рассмотрим пример 3 классов A, B и C, где C расширяет B, а B расширяет A.
источник
b instanceof A
эквивалентноA.class.isAssignableFrom(b.getClass())
(как заметил ОП). Ваш пример верный, но не имеет значения.new Y()
может быть недопустимым, еслиY
он абстрактный или без общедоступного конструктора по умолчанию, вы можете сказать, чтоX x = (Y)null
он допустим тогда и только тогда, когда онx.getClass().isAssignableFrom(Y.class)
равен true.Есть и еще одно отличие:
нулевой экземпляр X не
false
имеет значения, что Xnull.getClass (). isAssignableFrom (X) сгенерирует исключение NullPointerException
источник
null instanceof X
(где X - некоторый класс, известный во время компиляции) всегда будет возвращатьсяfalse
.X.class.isAssignableFrom(null.getClass())
не так ли? Но да, вызовgetClass()
нулевой ссылки приведет к NPE.getClass()
не следует использовать сisAssignableFrom
в первую очередь - операция предназначена для ситуации отсутствия объектов. Если у вас есть ссылка на объектa
, использоватьa instanceof SomeClass
(если вы делаете знать типSomeClass
) илиsomeObject.getClass().isInstance(a)
(если вы не знаете типsomeObject
).Есть еще одно отличие. Если тип (класс) для проверки является динамическим, например, передается как параметр метода, instanceof не подойдет для вас.
но вы можете сделать:
Ой, я вижу, этот ответ уже покрыт. Может быть, этот пример кому-то полезен.
источник
this
),clazz.isInstance(this)
будет лучше в вашем примере.Эта ветка дала мне некоторое представление о том, как
instanceof
отличаетсяisAssignableFrom
, так что я решил поделиться чем-то своим.Я обнаружил, что использование
isAssignableFrom
единственного (возможно, не единственного, но, возможно, самого простого) способа спросить себя, может ли ссылка одного класса брать экземпляры другого, когда для сравнения есть экземпляры ни одного класса.Следовательно, я не нашел, что использование
instanceof
оператора для сравнения присваиваемости было бы хорошей идеей, когда у меня были только классы, если только я не собирался создавать экземпляр из одного из классов; Я думал, что это будет небрежно.источник
instanceof также не может использоваться с примитивными типами или универсальными типами. Как в следующем коде:
Ошибка: Невозможно выполнить проверку instanceof для параметра типа T. Вместо этого используйте его объект стирания, так как дальнейшая информация общего типа будет удалена во время выполнения.
Не компилируется из-за удаления типа, удаляющего ссылку времени выполнения. Тем не менее, код ниже будет скомпилирован:
источник
Рассмотрим следующую ситуацию. Предположим, что вы хотите проверить, является ли тип A суперклассом типа obj, вы можете перейти
... A.class.isAssignableFrom (obj.getClass ()) ...
ИЛИ
... объект A ...
Но решение isAssignableFrom требует, чтобы тип obj был здесь виден. Если это не так (например, тип obj может быть закрытым внутренним классом), эта опция отсутствует. Однако экземпляр решения всегда будет работать.
источник
obj
в этом примере) любого типа, вы можете вызвать открытыйgetClass()
метод для него, чтобы получить метаданные отражения для реализующего класса. Это верно, даже если этот реализующий тип класса не будет юридически видим в этом месте во время компиляции. Это нормально , потому что во время выполнения, для вас , чтобы держатьobj
ссылку, некоторый код путь , который в конечном счете сделал иметь законный доступ к классу создал один и дал (утечка?) Его вам.Приведенный выше псевдокод является определением, если ссылки типа / класса A можно назначить из ссылок типа / класса B. Это рекурсивное определение. Для некоторых это может быть полезно, для других это может сбивать с толку. Я добавляю это на тот случай, если кто-то найдет это полезным Это просто попытка поймать мое понимание, это не официальное определение. Он используется в определенной реализации Java VM и работает для многих примеров программ, поэтому, хотя я не могу гарантировать, что он охватывает все аспекты isAssignableFrom, он не полностью отключен.
источник
Разговор с точки зрения производительности "2" (с JMH):
Это дает:
Итак, мы можем сделать вывод: instanceof так же быстро, как isInstance () и isAssignableFrom (), не далеко (+ 0,9% времени выполнения). Так что нет никакой разницы, что бы вы ни выбрали
источник
Как насчет некоторых примеров, чтобы показать это в действии ...
источник
некоторые тесты, которые мы провели в нашей команде, показывают, что
A.class.isAssignableFrom(B.getClass())
работает быстрее, чемB instanceof A
. это может быть очень полезно, если вам нужно проверить это на большом количестве элементов.источник
instanceof
, я думаю, у вас есть серьезные проблемы с дизайном ...