序文
「効果的なJavaの」中国の第三版は、ジャワの基礎についての本で、この本は複数回私に推奨されていました。私のお気に入りの庭のブログブロガー含めCJ月、彼は「類人猿は、いくつかの良い書籍の価値が訪問をお勧めしますJavaプログラムを」自身のブログで働いていたにも推奨されて。各章を読んだ後に決めた良い人、に沿って、エッセイを書きながら、自分の思い出を深めます。あなたは間違った場所、不明瞭な文、または他の提案を書くために持っている場合、私はあなたに感謝し、あなたは私にメッセージを修正することができます願っています。
「効果的なJavaの」中国の第三版読むオンラインリンク:https://github.com/sjsdfg/effective-java-3rd-chinese/tree/master/docs/notes
何ですか
それは以前にオブジェクトを作成したとして、我々は同じ機能の対象を必要とする時間を参照する不要なオブジェクトは、その後、私たちは前にオブジェクトを再利用するのではなく、新しいものを作成することができます。この時点で、我々はまだ新しいオブジェクトを作成した場合、それは不要なオブジェクトです。
それは常に再利用することができ、そのようなAの前提条件では、「オブジェクトは不変です」。
どこで使用
- 正規表現
- オートボクシング
- 初期設定
どのように達成するために
私たちは、いくつか例を挙げると、どこ中指「を使用どこ」、最初はトップをターゲットにしている達成するために、正規表現、それは不必要なオブジェクトを作成します、我々はそれぞれのケースを見て、次のように、コードは次のとおりです。
/ ** *文字列はローマ数字が含まれているかどうかを判断するために、正規表現を使用して * * @author GongGuoWei * @email [email protected] * @date 2020年1月14日 * / パブリック クラスローマ数字{ 静的 ブールisRomanNumeral(文字列S){ 戻り s.matches( "^(=?。)* M(C [MD] |?D {0,3} C)" +「(X- [CL] | X-L {0,3}?) (I [XV] | V I {0,3}?)$ " ); } }
私たちは、文字列が正規表現に一致するかどうかをチェックするためにString.matchesメソッドを使用しますが、正規表現の内部マッチがパターン・インスタンスを作成するためには、パフォーマンスが重要なの場合の再利用に適していない、と一度だけ、それを使用しますガベージコレクトの対象です。パターは、有限状態マシンにコンパイルされた正規表現を必要とするので、価格が高価であり、パターン・インスタンスを作成します。
次のように、クラスの一部は、パターン明示的例(変化しない)、キャッシュそれに正規表現をコンパイルするために初期化されるように、パフォーマンスを向上させる、各インスタンスisRomanNumeralメソッド呼び出しに同じを再利用します。
/ ** * @Author GongGuoWei * @email [email protected] * @Date 2020年1月14日 * / パブリック クラスRomanNumerals02 { プライベート 静的 最終パターンROMAN = Pattern.compile( 「^(?=。)M *(C [MD] | D C {0,3})」? + "(X [CL] | L X {0,3})(I [XV] | V I {0,3})$"?)。 静的 ブールisRomanNumeral(文字列S){ リターンROMAN.matcher(S).matches(); } }
あなたが頻繁に呼び出すと、私たちは、パフォーマンスが大幅に改善されます上記のバージョンを改善しました。6.5倍高速。だけでなく、パフォーマンスを改善するだけでなく、目に見えない前に、パターン・インスタンスのfianl変更されたプロパティを作成し、名前を付けできるようにしている、名前が正規表現そのものよりも読みやすいです。あなたはisRomanNumeralクラスが初期化されますが、呼ばれなかった含まれている場合しかし、その後、ROMANプロパティが初期化する必要はありません。私たちは、初期化プロパティによって初期化遅延を排除するが、一般的に推奨することはできません。初期遅延は、複合体の実現につながる、と性能指標に改善の余地がありませんので。
ここでは、オートボクシング、私たちはどのように回避しないとき、見続けています。我々は、すべてのJavaは、基本タイプとパッケージの種類、自動ボクシングとアンボクシングを混ぜることができ、それを知っています。しかし、我々は例えば、同時に次の例をファジー使用していない、次のように、我々は、すべての正の整数の合計を計算する必要があります。
プライベート 静的 長い和(){ ロング和 = 0L 。 以下のための(長い I = 0; I <= Integer.MAX_VALUEで、I ++ ){ 合計 + = I。 } 戻り値の和。 }
このコードを実行した結果は正しいですが、私たちは間違った文字、変数長い合計を持っており、ロングを書きました。プログラムは31電源不要のロングインスタンス2を構築しようとしていること、この意味。私たちは長い間に変数の型を合計すると、私のマシンで実行時間を0.42秒に5.5秒から減少!!!使用ベーシックタイプベーシックタイプは、無意識のオートボクシングにボクシングでなく、注意を払うではありません。
以下は、初期設定で以下のように、我々は、JDBCデータベース接続オブジェクトが例示されている取ります。
/ ** * @Author GongGuoWei * @email [email protected] * @Date 2020年1月14日 * / パブリック クラスdemo02 { プライベート 静的な 最終文字列のURL = "" ; プライベート 静的な 最終文字列USERNAME =「」; プライベート 静的な 最終文字列PASSWORD =「」; 静的接続のgetConnection(){ 接続の接続 = NULL ; してみてください{ Class.forNameの( "はcom.mysql.jdbc.Driver" ); 接続 =たDriverManager.getConnection(URL、ユーザ名、パスワード); } キャッチ(ClassNotFoundExceptionが電子){ e.printStackTrace(); } キャッチ(のSQLException E){ e.printStackTrace(); } 戻り接続。 } }
私たちは、データベース接続オブジェクトを取得するたびに、オブジェクトは、接続を作成しますが、接続の構成データベースは、多くの場合、このオブジェクトの構築のコストが高価であるため、それぞれの時間を作成する必要はありません、同じ、およびJVMのゴミでありますリサイクル時に、また、メモリ使用量、および財産への損害を向上させます。私たちは以下のことを実現するために、クラスの初期化コードの一部としてそれを参照してください。
/ ** * @Author GongGuoWei * @email [email protected] * @Date 2020年1月15日 * / パブリック クラスdemo03 { プライベート 静的な 最終文字列のURL = "" ; プライベート 静的な 最終文字列USERNAME =「」; プライベート 静的な 最終文字列PASSWORD =「」; プライベート 静的な接続の接続= nullを。 静的{ 試み{ Class.forNameの( "はcom.mysql.jdbc.Driver" )。 接続 =たDriverManager.getConnection(URL、ユーザ名、パスワード); } キャッチ(ClassNotFoundExceptionが電子){ e.printStackTrace(); } キャッチ(のSQLException E){ e.printStackTrace(); } } パブリック 静的接続のgetConnection(){ 戻り接続。 } }
概要
オブジェクトを作成するために繰り返さないでください、それは価格が高価ではありません作成し、正しいですが、私たちは、オブジェクトを把握する必要があります。特に現代では、良いことである追加のオブジェクト、強化定義プログラム、シンプルさ、機能性を、作成するための安価なを作成するためのコストは、我々はコンストラクタを介して、それを作成するには、この時間は、より良い選択である場合にはJVMは、オブジェクトの高度に最適化され、低コストの回復を持っている、それは簡単です。ここで要約すると、キーワード言及して守備のコピーを、それは状況、繰り返し使用を変更することはできません確実にするために、高価なオブジェクトを作成する人を指します。
REUSE 守備の複製コストを作成するために必要な、安価なオブジェクトよりもはるかに大きいです。あなたは守備のコピーを必要とせずに再利用する場合、それは潜在的なエラーやセキュリティの脆弱性につながる、と使用しないで再利用する必要がある、それはプログラムのパフォーマンスとスタイルに影響を与えます。