キャストのパフォーマンスは、JVM の実装によって異なります。
JLS 5.5は、キャストの要件 (再帰アルゴリズムを含む) のみを決定しますが、実装に関する要件は設定しません。実際、5.5.3 のランタイム キャスト ルールも同じ方法で決定されます。提案されたアルゴリズムと同じ結果を生成するすべての JVM 実装は、適切な JVM として受け入れられます。
一般に、JVM はオブジェクトのランタイム タイプを調べる必要があるため、キャスト ダウンにC
はもう少し時間がかかります。にキャストする場合、 extendsA
であるため、同じチェックを行う理由はありません。B
A
実際、JVM はメソッドとフィールドの数を気にしません。リフレクションで調べることができるのと同じように、型階層を比較するだけです(o.getClass()
)
次のようにサンプル コードを作成しました。1 つはダウンキャスト、次にアップキャストです。
Object o = new Integer(1);
Integer i = (Integer) o;
Object o2 = i;
コンパイルされたバイトコードは次のとおりです。
0 new java.lang.Integer [16]
3 dup
4 iconst_1 <-- 1 as a parameter to the constructor
5 invokespecial java.lang.Integer(int) [18] <-- constructor
8 astore_1 [o] <-- store in 'o'
9 aload_1 [o]
10 checkcast java.lang.Integer [16] <-- DOWNCAST CHECK, SPECIAL BYTECODE
13 astore_2 [i]
14 aload_2 [i]
15 astore_3 [o2] <-- WITH UPCAST NO CHECK
そのため、特定のクラスでスタックの一番上にある要素をチェックする特定の JVM 命令があります。
アップキャストでは、チェックはまったくありません。
クラスのサイズ (フィールド、メソッド、実際のフットプリントの数)は重要ではありません。これは、キャスティングがClass
(実際にはオブジェクトであるメタデータ) を調べるためです。
階層レベルの数、および実装されているインターフェースの数 (インターフェースにキャストする場合)は重要です。これは、トラバース可能な継承/実装ツリーを確認するためです。
このチェックになんらかのキャッシュがないとしたら、私は驚くでしょう。