Java 言語のイディオム
1.サイクル
重要なループでは、ループの終了を判断するときにメソッド呼び出しを削除します。
例:
for(int i=0; i<collection.size();i++){ ... }
…と置き換えます
for(int i=0; n=collection.size();i<n;i++){...}
通常、ループ インデックスに関係のない項目はループの外に移動します。
for(int i=0; ターミナル=x.length;i<ターミナル;i++){x[i] = x[i]/scaleA *scaleB;}
それは次のようになります:
ダブルスケール =scaleB*scaleA;for(int i=0;terminal=x.length;i<terminal;i++){x[i] = x[i]/scale;}
2.弦
文字列の連結をなくす
長い文字列を作成する場合は、常に String の代わりに StringBuffter を使用してください。
StringBuffer スペースを事前に割り当てます。 StringBuffer sb = new StringBuffer(5000);
3.基本的なデータ型
重要なループでは基本的なデータ型を使用します (通常、int データはlong/double データより高速です)
基本データ型 (Boolean、Integer など) のラッピング クラスは、主に、渡されるメソッド パラメータが (基本データ型ではなく) オブジェクトへの参照である必要がある場合に使用されます。
すべての定数代数式で static Final 修飾子を使用して、定数を参照しやすくします (コンパイラーが定数式を事前計算します)。
4.異常な
例外は、例外のスローと catch ブロックの実行にコストがかかるような、単一の真のエラー条件に対してのみ使用されます (主に、例外の作成時にスレッド スタックのスナップショットを取得するため)。
例外は、条件が本当に例外的な場合にのみスローされます。例外をスローするには、まず新しいオブジェクトを作成します。
Throwable インターフェイスのコンストラクターは、fillInStackTrace() という名前のネイティブ メソッドを呼び出します。fillInStackTrace() メソッドはスタックをチェックし、呼び出しトレース情報を収集します。
処理中に新しいオブジェクトが作成されるため、例外がスローされるたびに、VM はコール スタックを調整する必要があります。
例外はエラー処理のみに使用する必要があり、プログラム フローの制御には使用しないでください。
メソッド呼び出しごとに複数の try/catch ブロックを実装するのではなく、try/catch ブロックに複数のメソッド呼び出しを配置することで、コンパイラとランタイムを最適化します。
try{ Some.method1(); //java1.4 の難点 }catch(method1Exception e){ 例外を処理する
1 // このコードを最適化します } try{ Some.method2() // java1.4 の難点 }catch(method2Exception e){ 例外を処理します
2 // このコードを最適化する } try{ Some.method3() // java1.4 の難点 }catch(method3Exception e){ 例外を処理する
3 // このコードを最適化します
}
次のように書く必要があります:
try{ Some.method1(); Some.method2(); //java1.4 の難点 }catch(method1Exception e){ 例外 1 を処理する }catch(method2Exception e){ 例外 2 を処理する }catch( Method3Exception e){ 例外 3 を処理する }
5.ベンチマーク
これらのヒントはすべて、プラットフォームと仮想マシンによって異なることに注意してください。
例: 一部のサーブレット コンテナでは、OutputStream を介してバイトを出力する方が高速です。
2. 他のコンテナでは、PrintWriter を介して文字を出力する方が高速になります。
これらのヒントでは、最も移植性の高い推奨事項について説明します
プラットフォーム上で何が最速かを判断するには、いくつかのベンチマークを実行する必要がある場合があります。
6. new キーワードを使用せずにクラスのインスタンスを作成する
new キーワードを使用してクラスのインスタンスを作成すると、コンストラクター チェーン内のすべてのコンストラクターが自動的に呼び出されます。
ただし、オブジェクトが Cloneable インターフェイスを実装している場合は、その clone() メソッドを呼び出すことができます。 clone() メソッドはクラス コンストラクターを呼び出しません。
デザイン パターンを使用する場合、ファクトリ モードを使用してオブジェクトを作成すると、 clone() メソッドを使用して新しいオブジェクト インスタンスを作成するのが非常に簡単になります。
たとえば、次は Factory パターンの典型的な実装です。
public static Credit getNewCredit() { return new Credit() }
最適化後:
private static Credit BaseCredit = new Credit(); public static Credit getNewCredit() { return (Credit) BaseCredit.clone();}
上記のアイデアは配列処理にも役立ちます。
7.ノンブロッキング I/O を使用する
Java バージョンが低い JDK は、ノンブロッキング I/O API をサポートしていません。 I/O ブロックを回避するために、一部のアプリケーションは大量のスレッドを作成します (より良い場合は、バッファー プールが使用されます)。この手法は、Web サーバー、見積およびオークション アプリケーションなど、同時 I/O ストリームをサポートする必要がある多くのアプリケーションで見られます。ただし、Java スレッドの作成にはかなりのオーバーヘッドが必要です。
JDK 1.4 では、ノンブロッキング I/O ライブラリ (java.nio) が導入されました。アプリケーションで古いバージョンの JDK が必要な場合は、ノンブロッキング I/O をサポートするパッケージがあります。
8.変数を繰り返し初期化しないでください
デフォルトでは、クラスのコンストラクターを呼び出すときに、Java は変数を特定の値に初期化します。すべてのオブジェクトは null に設定され、整数変数 (byte、short、int、long) は 0 に設定され、float 変数と double 変数は に設定されます。 0.0、論理値は false に設定されます。
これは、クラスが別のクラスから派生する場合に特に注意する必要があります。これは、 new キーワードを使用してオブジェクトが作成されると、コンストラクター チェーン内のすべてのコンストラクターが自動的に呼び出されるからです。
9.クラスの最終修飾子を指定してみてください
Final 修飾子を持つクラスは派生されません。 Java コア API には、java.lang.String など、final を適用する例が多数あります。 String クラスに Final を指定すると、length() メソッドをオーバーライドできなくなります。
さらに、クラスが Final として指定されている場合、そのクラスのすべてのメソッドが Final になります。 Java コンパイラは、すべての最終メソッドをインライン化する機会を探します (これは特定のコンパイラの実装によって異なります)。これにより、パフォーマンスが平均 50% 向上します。
10.可能な限りローカル変数を使用する
メソッドの呼び出し時に渡されるパラメーターと呼び出し中に作成される一時変数はスタック (Stack) に保存されるため、処理が高速になります。静的変数、インスタンス変数などの他の変数はヒープ内に作成されるため、速度が遅くなります。さらに、特定のコンパイラ/JVM によっては、ローカル変数がさらに最適化される場合があります。 「可能な限りスタック変数を使用する」を参照してください。
11.掛け算と割り算
次のコードを考えてみましょう。
for (val = 0; val < 100000; val +=5) { alterX = val * 8; myResult = val * }
最適化後:
for (val = 0; val < 100000; val += 5) { alterX = val << 3; myResult = val << }
変更されたコードでは、8 を乗算する演算は実行されなくなり、代わりに 3 ビットを左にシフトする同等の演算が使用され、1 ビットの各左シフトは 2 の乗算と同等になります。同様に、1 ビットの右シフト演算は 2 で除算することと同等です。シフト操作は高速ですが、コードが理解しにくくなる可能性があるため、コメントを追加することをお勧めします。
private static Credit BaseCredit = new Credit(); public static Credit getNewCredit() {return (Credit) BaseCredit.clone();}