본문 바로가기

Java/이펙티브 자바

이펙티브 자바 - 10장 예외

예외는 진짜 예외 상황에만 사용하라

예외를 사용해 루트를 종료한 케이스

예외를 잘못사용한예시다

 

jvm 구현자 입장에서 저렇게 작성된 코드에 최적화를 신경 쓰지 않았을 가능성이 크다.

 

예외는 예외 상황에서만 쓰자

 

복구할 수 있는 상황에는 검사 예외를, 프로그래밍 오류에는 런타임 예외를 사용하라

 

호출하는 쪽에서 복구할 것이라 여겨지면

검사 예외(Checked Exception) 을 던지고 아닌 경우엔 비검사 예외(Unchecked Exception)를 던지면 된다.

 

검사 예외는 try-catch 로 처리하거나 throw 를 이용해 바깥으로 전파시켜

메서드를 호출했을때 결과를 사용자에게 알려준다

 

Unchecked Exception 은 런타임 에러와 에러가 있는데, 프로그램에서 잡을 필요가 없거나 잡아도 실이 되는 경우다

복구가 불가능 할 수 있다.

 

 

필요 없는 검사 예외 사용은 피하라

꼭 필요한 곳에서만 검사 예외를 사용한다.

 

검사 예외 (checked Exception)을 없앨수있는방법

 

- 검사 예외 대신 빈 옵셔널을 반환한다. 단점은 어떤 에러가 발생했는지 알려주는 부가정보를 담을 수 없다

 

- 검사 예외를 던지는 메서드를 쪼개본다

 

메서드를 통해 예외가 던져질지 여부를 결정하는것.

조건문은 생기지만, 예외에 좀 더 유연할 수 있다.

 

하지만 역시, 상태 검사 메서드 (check and action) 이기 때문에

동기화 없이는 여러 스레드가 접근 했을때 안전 하지 않을 수 있다.

 

표준 예외를 사용하라

 

예외도 표준 예외를 사용하자.

다른 사람이 익히고 사용하기 쉽다.

 

 

추상화 수준에 맞는 예외를 던지라

 

관련 없어 보이는 예외가 나오면 당황 스러울 수 있다.

이 문제를 피하려면 상위 계층에서는 저수준의 예외를 잡아 자신에 맞는 예외로 바꿔 던져야 한다.

 

예외번역

예외연쇄

 

디버깅에 도움이 되게 고수준의 예외에 저수준의 예외를 넣어 보낼 수도있다.

오류를 분석하기 좋다.

 

메서드가 던지는 모든 예외를 문서화하라

 

 

검사 예외는 항상 따로따로 선언하고, 각 예외가 발생하는 상황을 자바독의 @throws 태그를 사용하여 정확히 문서화하자.

 

예외의 상세 메시지에 실패 관련 정보를 담으라

예외 정보를 보다 상세하게 해주면

실패한 상황을 보다 정확히 포착할 수 있다.

모든 매개변수와 필드의 값을 실패 메시지에 담는게 좋다.

 

 

Exception 에 정보를 담은 코드

 

가능한 한 실패 원자적으로 만들라

 

호출된 메서드가 실패해도 객체가 호출 전 상태를 유지하면, 그 객체는 여전히 정상적으로 사용할 수 있는 상태다.

이걸 실패 원자적이라 한다.

 

 

객체를 원자적으로 만드는 방법

 

1. 불변 객체로 설계한다.

2. 매개변수의 유효성을 로직이 수행되기 전에 검사한다

객체의 내부 상태를 변경하기 잠재적 예외의 가능성 대부분을 걸러낸다.

3. 객체의 임시 복사본에서 작업을 수행한 다음, 작업이 성공적으로 완료되면 원래 객체와 교체하기.

 

예외를 무시하지 말라

예외가 선언된 API는 그 메서드를 사용할 때 적절한 조치를 해야 한다는 뜻이다.

따라서 catch 블록을 비워두면 예외가 존재할 이유가 없다.

 

 

 

물론 예외를 무시해야 할 때도 있다. 예를 들어 FileInputStream을 닫을 때 그렇다. 파일의 상태를 변경하지 않았으니 복구할 것도 없고, 스트림을 닫는 것은 필요한 내용은 모두 다 읽었다는 뜻이기 때문이다.

그래도 예외를 무시하기로 했다면 catch 블록 안에서 그렇게 결정한 이유를 주석으로 남기고 예외 변수의 이름도 변경하자.