실패 원자적(failure-atomic) 예외가 발생해도 여전히 정상적으로 사용할 수 있는 상태라면 얼마나 좋을까? 호출된 메서드가 실패하더라도 해당 객체는 호출 전 상태를 유지해야한다. 실패 원자적인 메서드 만드는 방법 1) 불변 객체 [아이템 17]로 설계하기 불변 객체는 태생적으로 실패 원자적 불변 객체의 상태는 생성 시점에 고정되어 절대 변하지 않기 때문에 메서드가 실패해도 불안정한 상태에 빠지지 않는다. 2) 가변 객체의 메서드의 경우 작업 수행 전 매개변수의 유효성을 검사하기 [아이템 49] 객체의 내부 상태를 변경하기 전에 잠재적 예외 가능성 대부분을 걸러낼 수 있는 방법 public Object pop() { if (size == 0) //매개변수의 유효성 검사 throw new Empty..
예외 상세 메세지 예외를 잡지 못해 프로그램이 실패하면 자바 시스템은 그 예외의 스택 추적 정보(예외 객체의 toString 메서드를 호출)를 자동으로 출력한다. 그 정보로부터 실패원인을 분석해야하기 때문에 예외의 toString 메서드에 실패 원인에 관한 정보를 가능한 많이 담아 반환해야한다. 발생한 예외에 관련된 모든 매개변수,필드 값을 담아야함 → 무엇을 고쳐야 할지 분석하는 데 도움이 됨 장황할 필요는 없고, 예외 원인을 파악하기 쉬운 메세지가 좋다. public IndexOutOfBoundsException(int lowerBound, int upperBound, int index) { super(String.format( "최솟값: %d, 최댓값: %d, 인덱스: %d", lowerBound,..
예외 문서화 메서드가 던지는 예외는 그 메서드를 올바르게 사용하기 위한 중요한 정보이므로 예외 하나하나를 문서화하는 데 충분한 시간을 쏟아야한다. [아이템 56] 검사 예외는 항상 따로따로 선언하고, 각 예외가 발생하는 상황을 자바독의 @throws 태그를 사용하여 정확히 문서화하자. 공통 상위 클래스 하나로 예외를 던지는 것을 삼가자. ex)Exception, Throwable (main 메서드만 예외) 비검사 예외도 검사 예외처럼 정성껏 문서화해두면 좋음 → 그 메서드를 성공적으로 수행하기 위한 전제조건이 됨 메서드가 던질 수 있는 예외를 @throws 로 문서화하되, 비검사 예외는 메서드 선언의 throws 목록에 넣지 말자. (검사냐 비검사냐에 따라 API 사용자가 할 일이 달라지므로 확실히 구분..
메서드가 저수준 예외를 처리하지 않고 바깥으로 전파했을 때 수행하려는 일과 관련 없어 보이는 예외가 발생 내부 구현 방식을 드러내어 윗 레벨 API를 오염 구현 방식을 바꾸면 다른 예외가 발생하여 기존 클라이언트 프로그램을 깨지게함 예외 번역 (exception translation) 위 문제를 피하기 위해선 상위 계층에서 저수준 예외를 잡아 자신의 추상화 수준에 맞는 예외로 바꿔 던져야함 (예외 번역) try { // 저수준 추상화를 이용 } catch (LowerLevelException e) { // 추상화 수준에 맞게 번역 throw new HigherLevelException("exception"); } // AbstractSequentialList에서 수행하는 예외번역 예시 public abs..
표준 예외 자바 라이브러리는 대부분 API 에서 쓰기 충분한 수의 예외를 제공하므로 이를 재사용하자. 표준 예외를 재사용하면 장점이 많음 다른 사람이 익히고 사용하기 쉬움 예외 클래스 수가 적을수록 메모리 사용량과 클래스를 적재하는 시간을 아낄 수 있음 자주 사용되는 표준 예외 예외 주요 쓰임 IllegalArgumentException 허용하지 않는 값이 인수로 건네졌을 때 (null은 NullPointerException으로 처리) IllegalStateException 객체가 메서드를 수행하기에 적절하지 않은 상태 NullPointerException null을 허용하지 않는 메서드에 null을 건넸을 때 IndexOutOfBoundsException 인덱스가 범위를 벗어났을 때 Concurrent..
검사 예외를 제대로 활용하면 검사 예외를 제대로 활용하면 API와 프로그램의 질을 높임 (검사 예외는 처리하여 안전성을 높일 수 있기 때문) 검사 예외를 과하게 사용하면 검사 예외는 호출자가 처리해야하는 강제성을 지니기 때문에 부담을 주게 된다. 검사 예외를 던지는 메서드는 스트림 안에서 직접 사용할 수 없어서 [아이템 45~48] 부담을 주게 된다. 특히, 메서드가 단 하나의 검사 예외만 던질 때 부담이 큼 그 예외 하나 때문에 API 사용자는 try블록을 추가하고 스트림에서 사용하지 못하게 됨 이런 상황에선 검사예외를 안 던질 방법이 없는지 고민해보자 검사 예외 회피 방법 1) Optional [아이템 55] 적절한 결과 타입을 담은 옵셔널은 반환하는 것이 검사 예외를 회피하는 가장 쉬운 방법 검사 ..
Throwable 자바는 문제 상황을 알리는 타입(throwable)으로 검사 예외, 런타임 예외, 에러 이렇게 3가지를 제공 검사 예외 (Checked Exception) 호출하는 쪽에서 복구하리라 여겨지는 상황이면 검사 예외를 사용 검사 예외를 던지면 호출자가 그 예외를 catch로 처리하거나 더 바깥으로 던지도록 강제하게 된다. API 설계자는 API 사용자에게 검사 예외를 던져주어 그 상황에서 회복하라고 요구한 것 검사 예외는 Exception의 하위 클래스 중 RunitmeException을 상속하지 않는 것 호출자가 예외 상황에서 벗어나는 데 필요한 정보를 알려주는 메서드를 함께 제공하자. 비검사 예외 (Unchecked Exception) 프로그램에서 복구가 불가능하거나 더 실행해봐야 득보다..
// 예외를 완전 잘못 사용한 예 try { int i = 0; while (true) { range[i++].climb(); } } catch (ArrayIndexOutOfBoundsException e) { } 위 코드는 직관적이지 않게 예외를 작성하였다. 무한루프를 돌다가 배열의 끝에 도달해 예외가 발생하면 끝을 내는 것이다. 이 코드를 아래와 같이 작성 했다면 모든 프로그래머가 이해할 수 있을 것이다. for(Mountain m : range) m.climb(); 그런데 예외를 쓴 이유가 무엇일까? 3가지 면에서 잘못된 추론을 해서 예외를 사용한게 더 성능이 좋을 것이라고 생각했을 가능성이 있다. 이를 바로잡고자 한다. 1) 예외는 예외상황에 쓸 용도로 설계되어서 JVM 구현자 입장에서는 명확한 ..