8

行うことの間に違いはありますか

Field field = something.getSomethingElse().getField();
if (field == 0) {
//do something    
}
somelist.add(field);

if (something.getSomethingElse().getField() == 0) {
//do something    
}
somelist.add(something.getSomethingElse().getField());

ゲッターを介したフィールドへの参照はパフォーマンスの低下を招きますか、それとも割り当てられた変数を参照するのと同じですか? 変数は単なるメモリ空間への参照であることを理解しています。そのため、ゲッターはそのメモリ空間に到達するための別の方法である必要があります。

これは実用的な問題ではなく、学問的な問題 (単なる好奇心の学校) であることに注意してください。

4

9 に答える 9

12

それは無視できるほどの損害です。あまり気にしすぎると、時期尚早の最適化の餌食になってしまいます。アプリケーションが遅い場合、これが理由ではありません。

于 2009-07-28T18:29:05.587 に答える
8

getSomethingElse()が次のように定義され ていると仮定します。

public SomethingElse getSomethingElse() {
    return this.somethingElse;
}

パフォーマンスの差は最小限になります (インライン化される場合はゼロになります)。ただし、実際には常にそうであるとは限りません。バックグラウンドで何らかの処理が行われている可能性があります (必ずしもオブジェクト自体ではなく、たとえば AOP プロキシを介して)。そのため、繰り返しアクセスするために結果を変数に保存することをお勧めします。

于 2009-07-28T18:30:59.497 に答える
6

ゲッターを介して変数にアクセスすると、メソッドが呼び出されるという違いがあります。JVM は、状況によってはメソッド呼び出しを最適化できる可能性がありますが、それメソッド呼び出しです。

とはいえ、コードの最大のボトルネックまたはパフォーマンスの問題がアクセサー メソッドのオーバーヘッドである場合は、あまり心配する必要はないと言えます。

于 2009-07-28T18:30:04.507 に答える
4

パフォーマンスの低下があります (非常に小さいため、無視できる場合があります)。ただし、JVM はパフォーマンスを向上させるために、これとすべての呼び出しをインライン化する場合があります。

2番目の方法を残した方が良いでしょう。

于 2009-07-28T18:29:21.247 に答える
3

Sun の HotSpot のような優れた JVM を使用している場合は、そうではありません。getter をインライン化して (ネイティブ コードに) コンパイルします。

ゲッターを使用することは、防御手段として、また一般的な情報隠蔽として、一般的に非常に優れた方法です。

于 2009-07-28T18:29:47.707 に答える
2

Java を使用して Android アプリケーションを作成する場合の注意点: http://developer.android.com/training/articles/perf-tips.html#GettersSetters

C++ のようなネイティブ言語では、フィールドに直接アクセスする (i = mCount) 代わりに、getter (i = getCount()) を使用するのが一般的です。これは C++ にとって優れた習慣であり、C# や Java などの他のオブジェクト指向言語でもよく行われます。これは、通常、コンパイラがアクセスをインライン化できるためです。また、フィールド アクセスを制限またはデバッグする必要がある場合は、いつでもコードを追加できます。

ただし、これは Android では悪い考えです。仮想メソッドの呼び出しは、インスタンス フィールドのルックアップよりもはるかにコストがかかります。一般的なオブジェクト指向プログラミングの慣例に従い、getter と setter をパブリック インターフェイスに配置することは合理的ですが、クラス内では常にフィールドに直接アクセスする必要があります。

JIT を使用しない場合、フィールドへの直接アクセスは、単純な getter を呼び出すよりも約 3 倍高速です。JIT (直接フィールド アクセスはローカルにアクセスするのと同じくらい安価です) を使用すると、直接フィールド アクセスは単純な getter を呼び出すよりも約 7 倍高速です。

ProGuard を使用している場合は、ProGuard がアクセサーをインライン化できるため、両方の長所を活用できることに注意してください。

于 2014-10-06T10:32:56.757 に答える
0

この投稿では、JVMではなくCLI VMについて説明していますが、それぞれが同様のことを実行できるため、関連性があると思います。

私はこの特定の問題をJITのために特別な方法で処理しています。ここでの説明は概念的なものであり、パフォーマンス上の理由から、コードはわずかに異なる方法で実装していることに注意してください。アセンブリをロードするときに、単にメンバーフィールドを返す場合は、メソッド記述子にメモします。後で他のメソッドをJITするときcallは、バイトコード内のこれらのメソッドへのすべての命令をldfld、ネイティブコードジェネレーターに渡す前の命令に置き換えます。このようにして、私は次のことができます。

  1. JITの時間を節約します(JITにldfldかかるプロセッサ時間は)よりも短くなりますcall
  2. ベースラインコンパイラでもインラインプロパティ。
  3. 概して、パブリックプロパティ/プライベートフィールドパターンを使用しても、デバッガーがデタッチされたときにいかなる種類のパフォーマンスペナルティも発生しないことが保証されます。(デバッガーが接続されている場合、アクセサーをインライン化できません。)

VMテクノロジーのビッグネームが、すでにこれに似た(そしておそらくそれよりも優れた)製品を実装していることは間違いありません。

于 2009-08-03T06:24:52.690 に答える
0

パフォーマンスの違いは気になりません。それについては考えずに、現実的なシナリオでコードのプロファイリングに時間を費やしたほうがよいでしょう。あなたはおそらくあなたのプログラムの遅い部分があなたが思っているところにないことに気付くでしょう。

于 2009-07-29T10:27:01.677 に答える
0

メソッドが処理を伴わない単純な getter である場合、それは問題ではありません。大規模な計算が含まれる場合、プロパティはとにかくあなたが望むことをしません。

違いについて心配するのは、膨大な回数 (数千回) の反復があるタイトなループの場合だけです。それでも、アスペクトを使用して余分な処理 (ログなど) を織り込んでいる場合にのみ問題になる可能性があります。これには、何千もの余分なオブジェクト (JoinPoints やパラメーターのオートボクシングなど) の作成が含まれ、結果として GC の問題が発生する可能性があります。

于 2009-07-28T18:37:53.993 に答える