以下の 2 つのコード スニペットの効率に違いはありますか? 最初のものは、オブジェクトにメモリを割り当てる必要がありますか?
Class c = a.getClass();
if(str != null)
c.dosomething(c.getX())
if(a.getClass() != null)
a.getClass().doSomething(a.getClass().getX());
以下の 2 つのコード スニペットの効率に違いはありますか? 最初のものは、オブジェクトにメモリを割り当てる必要がありますか?
Class c = a.getClass();
if(str != null)
c.dosomething(c.getX())
if(a.getClass() != null)
a.getClass().doSomething(a.getClass().getX());
どちらがより効率的かは、コードを実行するときにJITコンパイラとJVMが何をするかによって異なります。これらはプラットフォームと実装に依存するため、明確な答えを出すのは困難です。
クラスオブジェクトcに割り当てられたメモリはすべて、getClass()
メソッドに割り当てる必要があります。関数内のcは単なる参照であり、レジスタ内に格納されている可能性が高いため、メモリ割り当てが必要になります。関数呼び出しは、レジスタ内にデータを格納する場合に比べて比較的コストがかかります。ただし、JITが2番目のスニペットのバイトコードを最初のスニペットにリファクタリングするのに十分賢いとは思えないので、最初の方法の方がおそらく高速です。
ただし、コードスタイルのために、常に最初の方法を使用する必要があります。
特に getObject メソッドが高価な場合は、最初の方法がはるかに効率的です。c にメモリが割り当てられている場合、これは getObject メソッド内で行われます。
最初の形式の方が効率的である可能性があります。(そして、コードが JIT コンパイルされている場合に効率が低下することは想像に難くありません。)
getClass()
2 回目以降の呼び出しに副作用がなく、同じ結果が生成されることを JIT コンパイラが証明できる場合、最初の呼び出しで返された値を再利用できます。これにより、2 番目のフォームは 1 番目のフォームと同じくらい速く実行されます。
JIT が実際にこの最適化を実行できるかどうかは、JVM に依存します。私の直感では、現在の世代の JIT はおそらくそれを行わないでしょうが、私は間違っている可能性があります。念のため、JIT コンパイルされたネイティブ コードをダンプする必要があります。
次のことに注意してください。
getClass() 呼び出し (オーバーライドされていないと仮定) は、比較的安価になります。Class
オブジェクトのヘッダー内の何かに対応する既存のオブジェクトを検索するだけです。Class
( Java の仕様では、オブジェクトと Java の型の間には 1 対 1 の関係があると記載されているため、毎回新しいオブジェクトが作成されるわけではないことがわかっていClass
ます...)
このコードがパフォーマンスのボトルネックでない限り、どのように実装してもアプリケーション全体の速度に大きな違いはありません。(時期尚早の最適化に注意してください...)