ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 아이템9. try-finally 보다 try-with-resources 를 사용하라.
    Java/이펙티브 자바 2023. 6. 7. 10:17

    핵심정리

    - try-finally 는 더이상 최선의 방법이 아니다. (자바7부터)

    - try-with-resources를 사용하면 코드가 더 짧고 분명하다.

    - 만들어지는 예외 정보도 훨씬 유용하다.

    static String firstLineOfFile(String path) throws IOException {
        try (BufferedReader br = new BufferedReader(new FileReader(path))) {
            return br.readLine();
        }
    }

     

    문제 1. try-finally

    static void copy(String src, String dst) throws IOException {
        InputStream in = new FileInputStream(src);
        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 {
            in.close(); // 여기서 에러
            out.close();
        }
    }

    - out.close가 실행이 안될 수 도 있다.

     

    문제 2. try-finally

    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();
        }
    }

    - 코드에는 문제가 없지만, 코드가 너무 지저분하다.

     

    문제 3. try-finally

    public class TopLine {
        // 코드 9-1 try-finally - 더 이상 자원을 회수하는 최선의 방책이 아니다! (47쪽)
        static String firstLineOfFile(String path) throws IOException {
            BadBufferedReader br = new BadBufferedReader(new FileReader(path));
            try {
                return br.readLine();   // CharConversionException
            } finally {
                br.close();             // StreamCorruptedException
            }
        }
    
        public static void main(String[] args) throws IOException {
            System.out.println(firstLineOfFile("pom.xml"));     // 가장 나중에 발생한 예외인 StreamCorruptedException 가 보인다.
        }
    }

    - 가장 처음의 발생한 예외를 알 수 없다.

    - try-with-resources 를 사용한다면 두 가지 예외 순서대로 다 보인다.

     

     

    해결 방안1. try-with-resources

    // 코드 9-4 복수의 자원을 처리하는 try-with-resources - 짧고 매혹적이다! (49쪽)
    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);
            }
        }
    }

    - catch 문이나 finally 문도 사용 가능하다.

     

    완벽공략

    - p48, 자바 퍼즐러 예외 처리 코드의 실수

    static void copy(String src, String dst) throws IOException {
        InputStream in = new FileInputStream(src);
        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 {
            try {
                out.close();
            } catch (IOException e) {   // IOException 이 아니라 런타임ex이 터진다면 catch 문 X
                // TODO 안전한가?
            }
    
            try {
                in.close();
            } catch (IOException e) {
                // TODO 안전한가?
            }
    
        }
    }

     

    - p49, try-with-resources 바이트코드

        ㆍ중첩된 try-catch 문을 사용

        ㆍaddSuppressed 함수로 에러를 순서대로 담아줘서 출력 ( 첫번째 에러 보존 )

        ㆍclose 함수를 여러번 호출 - idempotent 

     

    댓글

Designed by Tistory.