[Effective java]オブジェクトの作成と破壊ではなくtry-with-resourcesを使用


この効果javaの開始は、オブジェクトの作成と破壊に関する考察です.
「第2章-オブジェクトの生成と破壊」は以下の基準で脈絡とする.
  • オブジェクトはいつ作成されますか?
  • オブジェクトを作成しないのはいつですか?
  • 正しいオブジェクトを作成する方法
  • 不要なオブジェクト作成を回避する方法
  • オブジェクトをタイムリーに破壊するにはどうすればいいですか?
  • 管理
  • 破壊前に実行する必要がある清掃作業の要領は何ですか?
  • 上の脈絡を覚えて勉強し続けましょう.
    Item1. ジェネレータではなく静的パラメータ法を考慮する.Item2. コンストラクション関数に多くのパラメータがある場合は、コンストラクタを考慮します.Item3. private作成者または列挙タイプを使用して、単一のループであることを保証します.Item4. インスタンス化を阻止するにはprivateジェネレータを使用します.Item5. リソースを直接指定するのではなく、依存オブジェクト注入を使用します.Item6. 不要なオブジェクトを作成しないでください.Item7. 書き上げたオブジェクトリファレンスを分解します.Item8. ロケータとクリーナーの使用を避けるItem9. try-with-resourcesではなくtry-finallyを使用します.

    <try-with-resourcesを使用して「try-finally」>


    Item 9は実際にはItem 8の延長線です.
    Item 8がオブジェクトを破棄する一般的な方法に問題があることを示している場合:
    Item 9はこのような状況のために解決策を提案していると考えられます.
    前述したように、割り当てられたリソースを効率的に回収する方法.
    オブジェクトを自動的に実装した後、クライアントで閉じます.
    問題は、クライアントがリソースを閉じるほど信頼できるものはないということです.
    見逃しやすい部分になる可能性もあります.
    インスタンスを使用してインスタンスを閉じることを考えているプログラマーは世界で何人いますか?
    closeをオフにしないと、最終的にリソースを回収できないため、パフォーマンスが低下する可能性があります.
    Item 8では、このような場合の安全網保険に使用するためのターミネータとクリーナーについて議論しています.
    私が言ったように、これは納得できる方法ではありません.
    これからは、リソースが正しく閉じられていることを確認するためのものを理解します.

    #   try-finally


    従来の方法はtry-finally構文です.
    次の例を示します.
    public class TopLine {
    
        static String firstLineOfFile(String path) throws IOException {
            BufferedReader br = new BufferedReader(new FileReader(path));
           
      		try {
                return br.readLine();
            } finally {
                br.close();
            }
    
        }
    
       public static void main(String[] args) throws IOException 	{	
            String path = args[0];
            System.out.println(firstLineOfFile(path));
        }
    }
    これは、ユーザ入力を受信するための非常に簡単な例です.
    try文で入力を受信します.
    finally文で入力オブジェクトを閉じます.
    上記の例を単純に見ると余計なことはありません.
    しかし、使用するリソースが2つある場合、どうすればいいのでしょうか.
    次の例を見ると感じがします.
    public class Copy {
        private static final int BUFFER_SIZE = 8 * 1024;
    
        static void copy(String src, String dst) throws IOException {
           
      	InputStream in = new FileInputStream(src);
           
      		try {
                OutputStream out = new FileOutputStream(dst);
               
      			try {
                    byte[] buf = new byte[BUFFER_SIZE];
                    int n;
                    while ((n = in.read(buf)) >= 0)
                        out.write(buf, 0, n);
                } finally {
                    out.close();
                }
           
      		} finally {
                in.close();
            }
        }
    
        public static void main(String[] args) throws IOException {
            String src = args[0];
            String dst = args[1];
            copy(src, dst);
        }
    }
    どうですか.上と違って、今回は入力も出力もしたいコードです.
    したがって、入力オブジェクトと出力オブジェクトの2つのリソースが使用されます.
    また、2つのリソースがあるため、重複するtry-finallyを使用しています.
    重ねて使うこと自体がダメというわけではなく、まず2つの問題が発生します.
    1つ目は瞬間コードが乱雑になったことです.
    毒性も低下します.
    2つ目は細かい例外処理ができないことです.
    try文とfinally文に異常が発生した場合、
    欠点は、2番目の例外が1番目の例外を飲み込むことです.
    この場合、正確な異常追跡ができないため、デバッグ自体が困難になる可能性があります.

    #   try-with-resources


    上記のtry-finally問題を解決したのはjava 7に現れたことです
    try-with-resources
    前に見た例を変えました.
    public class TopLine {
    
        static String firstLineOfFile(String path) throws IOException {
            try (BufferedReader br = new BufferedReader(
                    new FileReader(path))) {
                return br.readLine();
            }
        }
    
        public static void main(String[] args) throws IOException {
            String path = args[0];
            System.out.println(firstLineOfFile(path));
        }
    }
    違いはありますか?これがtry内のパラメータがリソースを伝達する方法です.
    1つのリソースしかないのであまり影響しない人のために、次の例を見てみましょう.
    public class Copy {
        private static final int BUFFER_SIZE = 8 * 1024;
    
        static void copy(String src, String dst) throws IOException {
            try (InputStream   in = new FileInputStream(src);
                 OutputStream out = new FileOutputStream(dst)) {
                byte[] buf = new byte[BUFFER_SIZE];
                int n;
                while ((n = in.read(buf)) >= 0)
                    out.write(buf, 0, n);
            }
        }
    
        public static void main(String[] args) throws IOException {
            String src = args[0];
            String dst = args[1];
            copy(src, dst);
        }
    }
    今は少しはっきり感じます.
    パラメータをtry文に渡そうとすると、
    いくらリソースがあっても、全体のコードは複雑になりません.
    try-with-resourcesセクションではcatch文も使用できます.
    次の例を見てみましょう.
    public class TopLineWithDefault {
    
        static String firstLineOfFile(String path, String defaultVal) {
         
     	 try (BufferedReader br = new BufferedReader(
                    new FileReader(path))) {
                return br.readLine();
            } catch (IOException e) {
                return defaultVal;
            }
        }
    
        public static void main(String[] args) throws IOException {
            String path = args[0];
            System.out.println(firstLineOfFile(path, "Toppy McTopFace"));
        }
    }
    上記のようにtry文で発生する可能性のある例外を処理するためにcatch文を使用します.
    最後にItem 9に対する筆者のコメントです.

    回収する必要があるリソースを処理する場合はtry-with-resourcesを使用します.
  • は例外ではありません.コードがより短く、より明確になります.
  • の例外情報を生成することも有用である.