Для разумной реализации Java:
Каждый объект имеет заголовок, содержащий, помимо прочего, указатель на тип времени выполнения (например, Double
или String
, но он никогда не может быть CharSequence
или AbstractList
). Предполагая, что компилятор времени выполнения (как правило, HotSpot в случае Sun) не может определить тип статически, необходимо выполнить некоторую проверку сгенерированного машинного кода.
Сначала необходимо прочитать указатель на тип времени выполнения. В любом случае это необходимо для вызова виртуального метода в аналогичной ситуации.
Для приведения к типу класса точно известно, сколько существует суперклассов, пока вы не нажмете java.lang.Object
, поэтому тип можно прочитать с постоянным смещением от указателя типа (фактически, первых восьми в HotSpot). Опять же, это аналогично чтению указателя метода для виртуального метода.
Тогда значение чтения просто нуждается в сравнении с ожидаемым статическим типом приведения. В зависимости от архитектуры набора команд, другая команда должна будет ветвиться (или иметь ошибку) на неправильной ветке. ISA, такие как 32-битный ARM, имеют условные инструкции и могут позволить грустному пути пройти через счастливый путь.
Интерфейсы более сложны из-за множественного наследования интерфейса. Обычно последние два приведения к интерфейсам кэшируются в типе времени выполнения. В самые первые дни (более десяти лет назад) интерфейсы были немного медленными, но это уже не актуально.
Надеюсь, вы видите, что подобные вещи в значительной степени не имеют отношения к производительности. Ваш исходный код важнее. С точки зрения производительности, самым большим ударом в вашем сценарии могут быть промахи в кеше от повсеместной погони за указателями объектов (информация о типах, конечно, будет распространена).