Für eine vernünftige Implementierung von Java:
Jedes Objekt hat einen Header, der unter anderem einen Zeiger auf den Laufzeittyp enthält (zum Beispiel Double
oder String
, aber es könnte niemals sein CharSequence
oder AbstractList
). Angenommen, der Laufzeit-Compiler (im Fall von Sun im Allgemeinen HotSpot) kann den Typ nicht statisch bestimmen, und der generierte Maschinencode muss einige Überprüfungen durchführen.
Zuerst muss der Zeiger auf den Laufzeittyp gelesen werden. Dies ist ohnehin erforderlich, um eine virtuelle Methode in einer ähnlichen Situation aufzurufen.
Für das Casting in einen Klassentyp ist genau bekannt, wie viele Oberklassen bis zu Ihrem Treffer vorhanden sind java.lang.Object
, sodass der Typ mit einem konstanten Versatz vom Typzeiger gelesen werden kann (tatsächlich die ersten acht in HotSpot). Dies ist wiederum analog zum Lesen eines Methodenzeigers für eine virtuelle Methode.
Dann muss der Lesewert nur noch mit dem erwarteten statischen Typ der Besetzung verglichen werden. Abhängig von der Befehlssatzarchitektur muss ein anderer Befehl auf einen falschen Zweig verzweigen (oder einen Fehler verursachen). ISAs wie 32-Bit-ARM verfügen über bedingte Anweisungen und können möglicherweise den traurigen Pfad durch den glücklichen Pfad führen.
Schnittstellen sind aufgrund der Mehrfachvererbung der Schnittstelle schwieriger. Im Allgemeinen werden die letzten beiden Casts zu Schnittstellen im Laufzeittyp zwischengespeichert. In den frühen Tagen (vor über einem Jahrzehnt) waren die Schnittstellen etwas langsam, aber das ist nicht mehr relevant.
Hoffentlich können Sie sehen, dass solche Dinge für die Leistung weitgehend irrelevant sind. Ihr Quellcode ist wichtiger. In Bezug auf die Leistung ist der größte Erfolg in Ihrem Szenario wahrscheinlich, dass Cache-Fehler auftreten, wenn Objektzeiger überall verfolgt werden (die Typinformationen sind natürlich häufig).