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