ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Item 9. try-finally보다는 try-with-resource를 사용하라
    백수의 개발/이펙티브 자바 2019. 8. 9. 19:12

     

    자바 라이브러리에는 InputStream, OutputStream, java.sql.Connection등 close메서드를 호출해 직접 닫아줘야 하는 자원이 많다.

    이러한 자원을 닫기 위한 수단으로 try-finally가 사용되었다.

     

    try-finally는 더 이상 자원을 회수하는 최선의 방책이 아니다!

    아래와 같은 try-finally를 통해 자원을 닫을 수 있다.

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

    그러나 자원을 하나 더 사용한다면 아래와 같이 코드가 작성될 것이다.

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

    이러한 작성 방법은 너무 지저분하다.

    또한 위의 두 코드 모두 예외가 try 블록과 finally 블록 모두에서 발생할 수 있다.

    쉽게 말해 firstLineOfFIle메서드에서 br.readLine()에서 예외가 발생할 수 하고, br.close()에서도 예외가 발생할 수 있다는 것이다.

    만약, br.close()에서 예외가 다시 발생한다면, br.readLine()에서 예외가 발생했다는 정보는 없고, br.close()에서 발생한 오류 정보만 제공받게 된다.

    AutoCloseable

    이러한 문제는 자바7에서 새롭게 추가된 try-with-resource를 통해 해결 가능하게 되었다.

    try-with-resource구조를 사용하기 위해서는 close메소드를 정의하기 위한 AutoCloseable 인터페이스를 구현해야한다.

     

    try-with-resource

    위의 try-finally로 구현한 코드를 try-with-resource로 구현하면 아래와 같다.

    static String firstLineOfFile(String path) throws IOException{
    	try(BufferedReader br = new BufferedReader(new FileReader(path))) {
    		return br.readLine();
    	}
    }
    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);
    		}
    	}
    }

    try-with-resource를 사용하게 되면 코드가 간결해지고, 가독성이 증가한다.

    이는 try 블록에 있는 내용들이 실행완료되면, 알아서 AutoCloseable의 close메서드가 호출되어 자원을 닫게된다.

    게다가 try-finally와 다르게 close에서 문제가 생기더라도 해당 예외가 숨겨진 채 try 블럭에서 발생 된 예외를 보여준다.

     

    try-fianlly와 동일하게 try-with-resource에서도 catch절을 사용할 수 있어 try문을 중첩하지 않고도 다수의 예외를 처리할 수 있다.

    static String firstLineOfFile(String path, String defaultVal) {
    	try(BufferedReader br = new BufferedReader(new FileReader(path))) {
    		return br.readLine();
    	} catch (IOException e){
    		return defaultVal;
    	}
    }

    마무리

    꼭 회수해야 하는 자원을 다룰 때는 try-finally 대신 try-with-resource를 사용해라.

    코드는 더 짧고 분명해지고, 만들어지는 예외 정보도 훨씬 유용하다.

    try-with-resource는 정확하고 쉽게 자원을 회수할 수 있다.

    댓글

Designed by Tistory.