2011-07-26 5 views
3

私は最後に何かを作ってからそれをループで使うと、パフォーマンスは向上しますが、それはすべてに良いことですか?ループがない場所がたくさんありますが、ローカル変数に最後を追加します。それはそれを遅くするか、それともまだ良いですか?常にFinalを使用しますか?

また、グローバル変数final(例:アンドロイドペイント)がある場所があります。ループで使用するときにローカルの最終にする必要はありませんか?

答えて

6

最初に考慮する必要があります。このコードを書くことができる最も単純で明瞭な方法は何ですか?しばしばこれはうまくいく。

finalローカル変数がパフォーマンスに大きな影響を与える可能性は低いです。あなたが長い方法を持っているときにそれらは明快さを助けることができますが、私は方法を分解する方が良い方法であることを提案します。ほとんどの変数を宣言することができた私の経験から

finalフィールドは小さな程度にパフォーマンスに影響を与えることができますが、それfinal作るために、より良い理由は、それが明確なこのフィールドは(もJITを助けた)変化したことがないことを確認することである

+0

フィールドに 'final'を追加すると、ローカル変数の' final'と非常に大きく異なります。フィールドを最終的にすることは、しばしば並行プログラミングにおけるプログラムの正確さを達成する絶対的な必要性である。 –

+0

新しいオブジェクトを別のスレッドに渡すという微妙な状況を除いて、(最終的な可能性があるが同じではないフィールドの場合は、この失敗の例は見ていない)。それを「最終」にすると、プリミティブまたは参照が変更できないため、スレッド安全性の問題がないことが明確になります。注:参照されるオブジェクトは依然として変更される可能性があります。 –

+0

私は仕様へのリンクを残しておきます。最終変数:http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.12.4最終フィールド:http://java.sun.com/docs/books/jls/third_edition /html/memory.html#66562 tl; dr:前者は文書化に役立ち、後でプログラムの動作を目立つように変更する可能性があります。 –

0

理論的には、ローカル変数finalを作成すると最適化できます。オプティマイザはおそらくあなたの地元の人が変わっていない時をすでに検出している可能性があるので、パフォーマンスを向上させることはできません。それは、それを少し助けることを傷つけることはできません。

状況によっては、1つの変数を2つに変更すると効果的です。この

String a = "foo"; 
if (lol) a += "bar"; 

for(.. 1000 ...) doSomething(a); 

final String a; 
{ 
    String ma = "foo"; 
    if (lol) ma += "bar"; 
    a = ma; 
} 

for(.. 1000 ...) doSomething(a); 

に免責事項から:私は、JITの専門家ではありません。

3

final

しかし、非常に醜いです。それがそれに対する私の主なポイントです。

プログラムの一部がパフォーマンスに重大でない場合は、早すぎる最適化に注意してください。

最終使用可変性を最小限にし、文書化の目的のために、彼らはインナー/匿名クラスで使用されている場合のみ、ローカル変数に最終的に使用する属性について:

ここ
2

は私の2セントです。

は、マイクロ最適化に使用しないでください。特にクラスやメソッドには使用しないでください。パフォーマンスが向上すると思うからです。クラスとメソッドを最終的にに設定して、の継承メソッドまたはオーバーライドメソッドを禁止します。

2

テストを容易にする以外の理由がない場合は、できる限り最終的なものを使用すること(クラスやメソッドではなくフィールドや変数)を使用するのが良い方法と考えられます。ファイナルは決してパフォーマンスに悪影響を与えません。

0

最終変数は定数であるため、コンパイラは変数参照命令ではなく定数値を生成する可能性があります。もちろん、それは速度を向上させるでしょう。

また、グローバル変数final(例:アンドロイドペイント)、それはループでそれを使用するとき、私はそれを地方の最終にする必要はないという意味ですか?

final int somefinalvalue = 0; 

void amethod() { 
    final int somefinalvalue = 0; // repeated from global one 
} 

または何:

申し訳ありませんが、あなたがする必要はありません意味ですか?グローバル変数と同じ名前のローカル変数を宣言すると、グローバル変数を「シャドー」することに注意してください。すなわち、実際はまったく異なる変数です。あなたが既にグローバルなものを持っているならば、それを使ってください。再宣言する必要はありません。

+0

私は彼がフィールドのローカルキャッシングを意味すると思う。 –

+0

javaでは、コンパイラがどのような値を持つかを知っているかのように、* constant *ではなく* immutable *です。コンパイラは代入を禁止します。 – marc

+0

@Marcだからこそ私はコンパイラが "できます"と言ったのですが、 "できません"。コンパイラが十分にスマートであれば、いくつかの分析を通じて、定数として最適化するかどうかを決定できます(整数や浮動小数点のような単純な値の場合のみ)。 – LeleDumbo

3

パフォーマンスについて考える必要はありません。オブジェクトメンバー(フィールド)のfinalはパフォーマンスを向上させる重要なメモリーセマンティクスを持っています(しかし、もっと重要なのは、コードを正しく機能させるためにしばしば必要です)。可能であれば、いつでもオブジェクトメンバーにfinalを置く必要があります。しかし、ローカル変数の場合、は、コードの読みやすさを向上させる場合にのみ使用するか、またはメンテナがコードに触れるとバグを防ぐことができます。

Javaコミュニティの一般的なコンセンサスは、すべてのローカル変数のfinalがコードを読みにくくすることです。パフォーマンス面では、ローカル変数はコンパイラで簡単に分析できるため、最適化がないと予想できます。言い換えれば、コンパイラはそれだけでそれを理解することができます。

0

@ perter-lawreyのように、これがあなたの最初の懸念事項であるとは思わないでしょう。まず、コンパイラの最適化は非常にトリックを行うことができます。第2に、生成されたクラスファイルを分析して同じことを実行できるツールがいくつかあります。例えば、ProGuard: java shrinker, optimizer, obfuscator, and preverifier.

1

final属性はパフォーマンスに影響しないはずです。例外:複数のスレッドが同じフィールドにアクセスするマルチスレッド環境で、それらをリロケートする必要があるかどうかを「知らない」。ローカル変数のfinalは、何の影響もありません。なぜなら、ローカルスコープ以外は何とかそれらにアクセスすることができるからです。 メソッドのfinalは、JITコンパイル中に影響を与える可能性があります。メソッドが最終的でコンパクトであれば、誰もそれを上書きすることはないので、コンパイラはループ内でインライン展開できます。 最終的な属性をDBから簡単にロードすることはできないので、通常は属性のfinalを使用しません。最後のメソッドを最後の属性に宣言します(私のコード内に決して割り当てません)。タイプミス。しかし、あなたが変数に適切な名前を使用し始めるなら、あなたはそのようなタイプミスを許しません。

関連する問題