- 자바 라이브러리에는
close
메서드를 호출해 직접 닫아줘야하는 자원이 많다.InputStream
,OutputStream
,Connection
- 자원 닫기는 클라이언트가 놓치기 쉬워서 예측할 수 없는 성능 문제로 이어지기 도 한다.
finally 블럭
try-catch문과 함께 예외 발생 여부에 관계 없이 실행되어야할 코드를 포함시키기 위해 사용
try { // 예외가 발생할 수 있는 코드 } catch { // 예외 처리를 위한 코드 } finally { // 예외 발생 여부와 관계없이 항상 실행되어야하는 코드 // finally 블럭은 항상 try-catch문의 마지막에 위치한다. }
순서
- 예외 발생 시, try-catch-finally
- 예외 미발생 시, try-finally
자원 반납법
하나만 반납할 때,
public String firstLineOfFiles(String path) { BufferedReader bufferedReader = new BufferedReader(new Filereader(path)) try { return bufferedReader.readLine(); } catch (IOExection e){ e.printStackTrace(); } finally { try { // close()는 예외를 발생시킬 수 있으므로 한 번더 감싸줘야한다. if (bufferedReader != null) { bufferedReader.close(); } } catch (IOExection e) { e.printStackTrace(); } } }
둘 이상 반납할 때,
public void copy(String src, String dst) { InputStream inputStream = new InputStream(src); try { OutputStream outputStream = new OutputStream(dst); try { byte[] buffer = new byte[BUFFER_SIZE]; int n; while ((n = in.read(buf)) >= 0) { outputStream.write(buf, 0, n); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (outputStream != null) { outputStream.close(); } } catch (IOExection e) { e.printStackTrace(); } } } catch (IOExection e) { e.printStackTrace(); } finally { try { if (inputStream != null) { inputStream.close(); } } catch () { e.printStackTrace(); } } }
문제점
- indent가 많이 늘어나 가독성이 떨어진다.
- try 블럭과 finally 블럭 모두 예외 발생 시, try 블럭의 예외는 무시된다.
(디버깅이 어려워진다.)
try-with-resource
JDK 1.7에서 추가
조건 : 사용하려는 자원이
AutoClosable
인터페이스를 구현한다public interface Autocloseable { void close() throws Exception; }
사용 시기 : 입출력(I/O) 관련 클래스 중 사용 후 반드시
close()
해야할 때사용 방법
- try-with-resource 의 괄호 안에 자원 선언
- try 블럭을 벗어나는 순간 자동으로
close()
호출
사용 예시
하나만 반납할 때,
public String firstLineOfFiles(String path) { try (BufferedReader bufferedReader = new BufferedReader( new Filereader(path))){ return bufferedReader.readLine(); } catch (IOExection e){ e.printStackTrace(); } }
둘 이상 반납할 때,
public void copy(String src, String dst) { try (InputStream inputStream = new InputStream(src); OutputStream outputStream = new OutputStream(dst)) { byte[] buffer = new byte[BUFFER_SIZE]; int n; while ((n = in.read(buf)) >= 0) { outputStream.write(buf, 0, n); } } catch (IOExection e) { e.printStackTrace(); } }
장점
- 간결하고 가독성이 좋다.
- try 구문 내의 코드와 코드에 나타나지 않은 close() 호출 양쪽 모두 예외 발생 시,
close()
의 예외는 숨겨지고 try 구문 내의 예외만 기록된다. close()
에서 발생된 예외는 스택추적 내역에 (Suppressed)라는 머리말과 함께 출력된다.
억제된 예외
두 예외가 동시에 발생할 수 없기 때문에 실제 발생한 예외를 출력하고,
close()
로 인해 발생된 예외는 억제된 예외로 다룬다.억제된 예외에 대한 정보는 실제 발생된 예외 내부에 저장된다.
Throwable
내부의 억제된 예외 관련 메서드void addSuppressed(Throwable execption); // 억제된 예외 추가 Throwable[] getSuppressed() // 억제된 예외(배열)을 반환
레퍼런스
'Develop > Java' 카테고리의 다른 글
표준 예외 vs 사용자 정의 예외 (0) | 2023.04.05 |
---|---|
추상 클래스와 인터페이스 (0) | 2023.04.04 |
다형성 (0) | 2023.04.04 |
제어자 (0) | 2023.04.04 |
메서드 오버라이딩(Overriding) (0) | 2023.04.04 |