item 72 : 표준 예외를 사용하라
표준 예외 재사용의 중요성 : 숙련된 프로그래머는 그렇지 못한 프로그래머보다 더 많은 코드를 재사용한다. 예외 처리도 마찬가지로, 재사용 가능한 표준 예외를 적극 활용하는 것이 좋다.
자바 라이브러리는 대부분의 API에서 사용하기 충분한 수의 예외를 제공하며, 이를 잘 활용하면 코드의 질을 높일 수 있다.
1. 표준 예외 재사용의 장점
1) 재사용의 이점
API가 익숙해진다: 표준 예외를 재사용하면, 다른 개발자가 여러분의 API를 익히고 사용하는 데 큰 도움이 된다. 이미 익숙한 예외를 사용하면 코드가 더욱 읽기 쉽고, 낯선 예외로 인해 생길 수 있는 혼란을 방지할 수 있다. 예를 들어, 많은 자바 프로그래머는
IllegalArgumentException
이나NullPointerException
과 같은 표준 예외에 익숙하기 때문에, 이러한 예외를 활용하면 개발자들이 API를 사용하는 데 있어 추가적인 학습 부담이 줄어든다.메모리 효율성: 예외 클래스의 수가 적을수록 메모리 사용량이 줄고 클래스 적재 시간도 줄어든다. 표준 예외를 재사용하는 것은 성능상으로도 이점이 있다. 새로운 예외 클래스를 정의할 때마다 JVM은 이를 메모리에 로드하고 유지해야 하므로, 재사용 가능한 표준 예외를 사용하면 이러한 리소스 소비를 줄일 수 있다.
2) 자주 사용되는 표준 예외들
IllegalArgumentException: 잘못된 인수가 메서드에 전달될 때 사용된다. 예를 들어, 반복 횟수를 지정하는 매개변수에 음수를 건넬 때 사용한다. 이 예외를 통해 메서드에 전달된 인수가 유효하지 않다는 점을 명확하게 표현할 수 있다.
IllegalStateException: 객체의 상태가 메서드를 수행하기에 적합하지 않을 때 던진다. 예를 들어, 객체가 제대로 초기화되지 않은 경우 사용한다. 이 예외는 메서드를 호출할 시점에 객체가 올바른 상태에 있지 않다는 것을 알려주는 데 유용하다.
2. 표준 예외 목록과 사용 예시
예외
주요 쓰임
IllegalArgumentException
허용하지 않는 값이 인수로 건네졌을 때 (null은 제외)
IllegalStateException
객체가 메서드를 수행하기에 적절하지 않은 상태일 때
NullPointerException
null을 허용하지 않는 메서드에 null을 건넸을 때
IndexOutOfBoundsException
인덱스가 범위를 넘어섰을 때
ConcurrentModificationException
허용하지 않는 동시 수정이 발견됐을 때
UnsupportedOperationException
호출한 메서드를 지원하지 않을 때
1) 예외별 사용 예시
IllegalArgumentException 사용 예시
잘못된 인수가 전달되었을 때 사용한다. 예를 들어, 반복 횟수나 길이를 설정할 때 음수와 같은 잘못된 값이 전달되면 IllegalArgumentException을 던진다. 이는 호출자가 잘못된 인수를 전달했을 때 즉각적인 피드백을 제공하여 문제를 빠르게 인식하고 수정할 수 있게 한다.
IllegalStateException 사용 예시
객체의 현재 상태가 메서드를 수행하기에 적절하지 않은 경우 사용한다. 예를 들어, 객체가 초기화되지 않은 상태에서 메서드가 호출되는 경우 IllegalStateException을 던진다. 이 예외를 통해 객체가 올바른 상태에 있지 않음을 명확히 알릴 수 있어, 호출자가 이를 바로잡을 수 있다.
3. 재사용하기 좋은 예외와 사용 지침
1) NullPointerException
NullPointerException은 null을 허용하지 않는 메서드에 null이 전달될 때 던진다. 일반적으로 IllegalArgumentException 대신 사용하며, null 값을 다룰 때 명확한 의미 전달이 가능하다. 예를 들어, 메서드가 특정 객체를 필요로 하는데
null
이 전달되면, NullPointerException을 던짐으로써 호출자가 해당 객체가 필요하다는 점을 분명히 이해할 수 있다.
2) IndexOutOfBoundsException
IndexOutOfBoundsException은 인덱스 값이 허용된 범위를 벗어날 때 던진다. 이 예외는 컬렉션이나 배열의 인덱스가 잘못되었을 때 주로 사용한다. 예를 들어, 배열의 길이가 10인데 인덱스 값으로 11을 전달하려는 경우, IndexOutOfBoundsException을 던져서 인덱스가 유효 범위를 벗어났다는 것을 명확하게 알린다.
3) ConcurrentModificationException
ConcurrentModificationException은 단일 스레드에서 사용하려고 설계한 객체를 여러 스레드가 동시에 수정하려 할 때 던진다. 이 예외는 문제가 생길 가능성을 경고하는 역할을 하며, 동시 수정이 확실히 검출되지 않을 수 있다는 점에서 주의해야 한다. 예를 들어, ArrayList 같은 컬렉션은 동시 수정이 허용되지 않으므로, 두 개 이상의 스레드가 동시에 수정하려 하면 이 예외를 던진다. 이는 개발자가 동시성 문제를 인식하고 적절히 해결할 수 있도록 돕는다.
4) UnsupportedOperationException
UnsupportedOperationException은 클라이언트가 요청한 동작을 대상 객체가 지원하지 않을 때 던진다. 예를 들어, 원소 추가가 불가능한 컬렉션에서
add()
메서드를 호출하면 이 예외를 던진다. 이 예외는 해당 기능이 구현되지 않았거나 지원되지 않음을 명확히 알리기 위해 사용된다. 따라서 호출자는 해당 객체가 어떤 기능을 지원하지 않는지 쉽게 파악할 수 있다.
4. 재사용하지 말아야 할 예외
Exception, RuntimeException, Throwable, Error는 직접 재사용하지 않는 것이 좋다. 이 예외들은 추상 클래스와 같은 개념으로, 여러 성격의 예외를 포괄하므로 안정적으로 테스트할 수 없다.
이 예외들은 다른 예외의 상위 클래스이므로, 구체적인 의미 전달이 어렵고 불안정한 코드가 될 수 있다. 따라서 구체적인 표준 예외를 재사용하거나, 상황에 맞는 예외를 새로 정의하는 것이 좋다.
💡 핵심 정리
표준 예외를 재사용하면 코드의 가독성과 유지보수성이 높아진다. 표준 예외는 이미 많은 개발자가 익숙하게 사용하고 있기 때문에, API 사용성이 향상된다.
IllegalArgumentException과 IllegalStateException은 가장 자주 재사용되는 예외로, 잘못된 인수나 객체 상태에 대해 명확히 표현할 수 있다.
상황에 부합하는 표준 예외가 있다면 항상 재사용하는 것이 좋으며, 필요하다면 확장하여 사용해도 된다.
예외의 사용 목적과 던져지는 맥락이 일치할 때만 표준 예외를 재사용하도록 한다.
부가설명: 예외를 적절하게 사용하면 프로그램의 안정성과 유지보수성이 향상된다. 예외를 통해 잘못된 사용을 명확히 알리고, API 사용자에게 올바른 사용 방법을 강제할 수 있다. 또한, 표준 예외를 재사용함으로써 개발자는 보다 일관되고 예측 가능한 코드를 작성할 수 있다.
올바른 예외 사용은 프로그램의 안정성을 높이고, 유지보수 비용을 줄이는 중요한 요소이다.
Last updated
Was this helpful?