#java #performance #complexity-theory
#java #Производительность #сложность — теория
Вопрос:
Мне было интересно, насколько дорого в вычислительном отношении использование instanceof operator в java, и я хотел узнать, есть ли какие-либо лучшие альтернативы
Комментарии:
1. Есть ли какие-либо альтернативы, зависит от того, что вам нужно сделать…
Ответ №1:
Альтернативой является отказ от использования instanceof
и правильного проектирования ваших классов (в смысле OO).
Поскольку instanceof
оператор имеет соответствующую инструкцию байтового кода «instanceof«, вероятно, не будет более эффективного подхода; но это также может зависеть от того, как оптимизируется фактическая JVM.
Комментарии:
1. Это скорее комментарий, чем ответ. По сути, вопрос заключается в том, «Чтобы сделать X (где X не указано) Я должен выполнить Y; насколько быстро Y и есть ли какие-либо альтернативы? » Вы предлагаете вообще не делать X, что не касается точки OP.
2. @MichaelMcGowan: По моему опыту
instanceof
, это часто связано с плохим дизайном. Для меня не использовать его — лучшая альтернатива. И если вы его не используете, вам не нужно беспокоиться о его производительности.3. Я полностью согласен с тем, что это часто связано с плохим дизайном. Однако это не означает, что это всегда так, и иногда по разным причинам приходится сталкиваться с плохим дизайном.
4. @MichaelMcGowan самый быстрый способ что-либо сделать — это не делать этого, поэтому всегда следует искать альтернативу. Это метод нулевой гипотезы.
Ответ №2:
instanceof
это чертовски быстро. Однако, как правило, это признак плохо продуманного дизайна.
Он будет иметь примерно ту же производительность, что и (успешное) приведение, поскольку он делает почти то же самое. Действительно, задача примерно эквивалентна вызову «виртуального» метода.
В нормальных реализациях: для классов просто нужно получить класс среды выполнения и посмотреть на фиксированное смещение, чтобы проверить суперкласс (при условии, что у вас нет цепочки наследования из более чем восьми классов для HotSpot). Интерфейсы немного сложнее, но, как правило, последние два используемых случая для любого конкретного класса среды выполнения кэшируются. Так что это тоже быстро.
Ответ №3:
Я предполагаю, что вы действительно профилировали свой код и обнаружили, что ваше использование instanceof
является нетривиальным снижением производительности? Если нет, вы почти наверняка решаете проблему, на решение которой не стоит тратить время.
Если все, что вы делаете, это код, подобный этому:
if ( something instanceof MyClass ) {
MyClass mySomething = (MyClass) something;
//...
} else {
//exceptional case
}
Тогда, возможно, было бы возможно сначала попробовать приведение и разрешить ClassCastException
быть вашим «исключительным случаем»:
try {
MyClass mySomething = (MyClass) something;
} catch (ClassCastException cce) {
//exceptional case
}
Теперь, хотя это может быть преждевременной оптимизацией, не было бы преждевременным переосмыслить ваш дизайн. Чрезмерное instanceof
использование — это запах дизайна. В общем, вы должны использовать дженерики и полиморфизм таким образом, чтобы сократить количество раз, которое вы будете использовать instanceof
(и, действительно, приводить) к (почти) нулю.
-
Если в зависимости от типа объекта должен выполняться разный код, подумайте о том, чтобы сделать этот код методом экземпляра объекта и чтобы разные типы соответствовали интерфейсу.
-
Если вы обнаружите, что «знаете», что объект имеет определенный тип, но вы сделали какой-то шаг, из-за которого компилятор теряет этот факт (например, вы помещаете его в raw
List
), он может быть кандидатом на генерацию.
Ответ №4:
Если вы хотите проверить, является ли объект экземпляром определенного класса (но не является ли он extends
или implements
она), возможно, сравнение классов с ==
будет быстрее :
o.getClass() == YourClass.class
В противном случае, поскольку instanceof
ключевое слово было создано для этой конкретной цели, я не вижу, как вы могли бы добиться большего..
Комментарии:
1. Я не думаю, что это быстрее, потому что `ref instanceof class` напрямую отображается в
instanceof
операцию байт-кода. Ваш подход добавляет вызов методаgetClass
.2. Сравнение, которое вы пытаетесь выполнить
getClass
, не будет работать при попытке проверить, принадлежит ли объект также к определенному подклассу. Например, если у вас естьFileReader
расширениеInputStreamReader
, которое, в свою очередь, расширяет / реализуетReader
, вызовgetClass
объекта, созданного сnew FileReader
помощью, никогда не даст ничего, кромеFileReader
class , и поэтомуo.getClass() == Reader
илиo.getClass() == InputStreamReader
оба будут оцениватьfalse
.instanceof
, с другой стороны, дастtrue
результат во всех трех случаях класса.