Ответ зависит от деталей реализации, но в этой форме он не верен. Фактически, автор уже пытается уклониться от проверки фактов, используя слово «слегка», чтобы открыть возможность того, что вы никогда не увидите такой разницы в производительности.
Как уточнил этот ответ , идея такого утверждения заключается в том, что обычный класс имеет таблицу переопределяемых методов (также известную как «vtable»), которая наследуется подклассами, которые могут добавлять новые методы в конце и замените записи таблицы для методов, которые они переопределяют. Следовательно, первое разрешение должно только найти индекс таблицы, который можно запомнить, поэтому последующие вызовы должны вызывать только метод фактического класса получателя с этим индексом.
Поскольку интерфейсы могут быть реализованы разными классами, не имеющими отношения наследования, методы реализации могут иметь разные индексы таблиц для этих классов. Один из способов решить эту проблему - это иметь какое-то отображение из таблицы интерфейса в таблицу фактических классов. Предполагая, что такого рода двойная диспетчеризация приводит к предположению, что вызов интерфейсных методов был медленнее, чем обычных методов.
Однако JVM, такие как HotSpot JVM, не используют такую двойную диспетчеризацию. Они разрешают вызовы метода интерфейса для фактического класса получателя, как и любой другой вызов виртуального метода. Пока получатель является частью той же иерархии классов, скажем, вы вызываете метод на интерфейсе Appendable
, а получатель всегда является подклассом класса Writer
, никаких дополнительных шагов не требуется. Для большинства всех вызовов метода интерфейса это работает довольно хорошо.
Существуют случаи, когда вызов метода интерфейса заканчивается в разных реализациях несвязанных классов, скажем, когда вызов метода Appendable
иногда заканчивается в StringBuilder
, а другие в Writer
, но затем У нас есть несравненный сценарий. Этот конкретный вызов может быть немного медленнее, чем обычный вызов метода, но, поскольку невозможно создать тот же сценарий с абстрактным классом, нет смысла говорить, что он был медленнее, чем использование абстрактного класса.
Для частей кода, имеющих отношение к производительности, также известных как «горячие точки», JVM будет выполнять оптимизацию времени выполнения, которая в любом случае делает такое техническое различие несущественным. Даже крошечные издержки обычного вызова виртуального метода обычно устраняются, поскольку последующие оптимизации в значительной степени зависят от способности агрессивно встроить код целевого метода, чтобы иметь возможность использовать контекст вызывающей стороны и его известные окружающие условия для оптимизации код звонящего.