сложность экземпляра оператора java

#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 (и, действительно, приводить) к (почти) нулю.

  1. Если в зависимости от типа объекта должен выполняться разный код, подумайте о том, чтобы сделать этот код методом экземпляра объекта и чтобы разные типы соответствовали интерфейсу.

  2. Если вы обнаружите, что «знаете», что объект имеет определенный тип, но вы сделали какой-то шаг, из-за которого компилятор теряет этот факт (например, вы помещаете его в 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 результат во всех трех случаях класса.