-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
Showing
1 changed file
with
63 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# item69. 예외는 진짜 예외 상황에만사용하라 | ||
|
||
### 예외는 정말 예외적인 상황에서만 사용해야 한다. | ||
- 예외는 오직 예외 상황에서만 사용해야 한다. 절대로 일상적인 제어 흐름용으로 쓰여선 안된다. | ||
- 이를 프로그래머에게 API를 만들어서도 안된다. | ||
|
||
### 예외를 사용하는 부적절한 예 | ||
```java | ||
// 코드 69-1 예외를 완전히 잘못 사용한 예 - 따라 하지 말 것! (419쪽) | ||
try { | ||
int i = 0; | ||
while(true) | ||
range[i++].climb(); | ||
} catch (ArrayIndexOutOfBoundsException e) { | ||
} | ||
``` | ||
- 이 코드는 반복문을 종료하는 용도로 예외를 사용한다. | ||
- 직관적이지 않다는 점 외에 성능 문제도 있다. | ||
|
||
### 표준적인 관용구를 사용한 반복문 | ||
```java | ||
// 코드 69-2 표준적인 관용구를 사용한 반복문 (419쪽) | ||
for (Mountain m : range) | ||
m.climb(); | ||
``` | ||
- 위 코드는 표준적인 관용구를 사용한 반복문이다. | ||
- 이 코드는 예외를 사용하지 않으므로 성능도 훨씬 좋다. | ||
|
||
### API 설계와 관련된 예외 사용 사례 | ||
잘 설계된 API라면 클라이언트가 정상적인 제어 흐름에서 예외를 사용할 일이 없게 해야 한다. | ||
|
||
1. 상태 검사 메서드 | ||
특정 상태에서만 호출할 수 있는 ***상태 의존적 메서드***를 제공하는 클래스는, ***상태 검사 메서드도 함께 제공***한다면 예외를 사용하지 않을 수 있다.</br> | ||
`Iterator` 인터페이스를 예시로 들어보자. `next` 는 상태 의존적 메서드, `hasNext` 는 상태 검사 메서드에 해당한다. | ||
```java | ||
// 두 메서드 덕분에 표준 for 관용구를 사용할 수 있음 | ||
for (Iterator<Foo> i = collections.iterator(); i.hasNext(); ) { | ||
Foo foo = i.next(); | ||
} | ||
``` | ||
|
||
만약 `Iterator` 가 `hasNext`를 제공하지 않았다면 그 일을 다음과 같이 클라이언트가 대신 했어야 할 것이다.</br> | ||
```java | ||
try { | ||
Iterator<Foo> i = collection.iterator(); | ||
while(true) { | ||
Foo foo = i.next(); | ||
... | ||
} catch (NoSuchElementException e) { | ||
} | ||
``` | ||
이처럼 반복문에 예외를 사용하면 코드가 헷갈리고 성능도 좋지 않으며, 엉뚱한 곳에서 발생한 버그를 본의 아니게 숨기기도 한다. | ||
|
||
2. 옵셔널 반환 | ||
상태 검사 메서드 이외에, 올바르지 않은 상태일 때 빈 `Optional` 혹은 `null` 같은 특수한 값을 반환하는 방법도 존재한다. | ||
|
||
### 상태 검사 메서드, 옵셔널, 특정 값 중 하나를 선택하는 지침 | ||
- 외부 동기화 없이 여러 스레드가 동시에 접근할 수 있거나 외부 요인으로 상태가 변할 수 있다면 옵셔널이나 특정 값을 사용한다. 상태 검사 메서드와 상태 의존적 메서드 호출 사이에 객체의 상태가 변할 수 있기 때문이다. | ||
- 성능이 중요한 상황에서 상태 검사 메서드가 상태 의존적 메서드의 작업을 일부 중복 수행한다면 옵셔널이나 특정 값을 선택한다. | ||
- 다른 모든 경우엔 상태 검사 메서드 방식이 좋다. 가독성이 좋고, 잘못 사용했을 때 발견하기 쉽기 때문이다.(상태 검사 메서드 호출을 잊었다면 메서드는 예외를 던질것이다.) 옵셔널은 괜찮지만, 특정 값은 검사하지 않고 지나쳐도 발견하기 어렵다. | ||
|
||
### 핵심 정리 | ||
예외는 예외 상황에서 쓸 의도로 설계되었다. 정상적인 제어 흐름에서 사용해서는 안 되며, 이를 프로그래머에게 강요하는 API를 만들어서도 안 된다. |