Pour une implémentation raisonnable de Java:
Chaque objet a un en-tête contenant, entre autres, un pointeur vers le type d'exécution (par exemple Double
ou String
, mais il ne pourrait jamais être CharSequence
ou AbstractList
). En supposant que le compilateur d'exécution (généralement HotSpot dans le cas de Sun) ne peut pas déterminer le type de manière statique, une vérification doit être effectuée par le code machine généré.
Tout d'abord, ce pointeur vers le type d'exécution doit être lu. Ceci est de toute façon nécessaire pour appeler une méthode virtuelle dans une situation similaire.
Pour la conversion en un type de classe, on sait exactement combien de superclasses il y a jusqu'à ce que vous frappiez java.lang.Object
, de sorte que le type peut être lu à un décalage constant par rapport au pointeur de type (en fait les huit premières dans HotSpot). Encore une fois, cela revient à lire un pointeur de méthode pour une méthode virtuelle.
Ensuite, la valeur de lecture a juste besoin d'une comparaison avec le type statique attendu de la distribution. En fonction de l'architecture du jeu d'instructions, une autre instruction devra brancher (ou faire une erreur) sur une branche incorrecte. Les ISA tels que ARM 32 bits ont une instruction conditionnelle et peuvent être capables de faire passer le triste chemin par le chemin heureux.
Les interfaces sont plus difficiles en raison de l'héritage multiple d'interface. Généralement, les deux derniers transtypages vers les interfaces sont mis en cache dans le type d'exécution. AU tout début (il y a plus de dix ans), les interfaces étaient un peu lentes, mais ce n'est plus pertinent.
J'espère que vous pouvez voir que ce genre de chose est largement sans rapport avec les performances. Votre code source est plus important. En termes de performances, le plus gros succès de votre scénario est susceptible d'être des échecs de cache dus à la poursuite des pointeurs d'objet partout (les informations de type seront bien sûr communes).