728x90
69. 예외는 진짜 예외 상황에만 사용하라
// 69-1 예외를 완전히 잘못 사용한 예 - 따라하지 말 것!
try {
int i = 0;
while(true) { // 절대 좋지 않은 코드
range[i++].climb();
}
} catch (ArrayIndexOutOfBoundsException e){
}
// 표준적인 관용구로 하면 이해하기 쉽고 try는 필요하지 않다,
for (Mountain m : range) {
m.climb();
}
for ( Iterator<Foo> i = collection.iterator(); i.hashNext(); ) {
Foo foo = i.next();
...
}
// 컬렉션을 이런 식으로 순회하지 말 것!
try {
Iterator<Foo> i = collection.iterator();
while (true) {
Foo foo = i.next();
...
}
} catch (NoSuchElementException e){
}
70. 복구할 수 있는 상황에는 검사 예외를, 프로그래밍 오류에는 런타임 예외를 사용하라
71. 필요 없는 검사 예외 사용은 피하라
// 검사 예외와 비검사 예외 중 어느 것을 선택해야 할지는 프로그래머가 그 예외를 어떻게 다룰지 생각해보면 알 수 있다.
} catch (TheCheckedException e) {
throw new AssertionError(); // 일어날 수 없다!
}
} catch (TheCheckedException e) {
e.printStackTrace(); // 이런, 우리가 졌다.
System.exit(1);
}
// 71-1 검사 예외를 던지는 메서드 - 리팩토링 전
try {
obj.action(args);
} catch (TheCheckedException e) {
... // 예외 상황에 대처한다.
}
// 71-2 상태 검사 메서드와 비검사 예외를 던지는 메서드 - 리팩토링 후
if (obj.actionPermitted(args) {
obj.action(args);
} else {
... // 예외 상황에 대처한다.
}
obj.action(args);
72. 표준 예외를 사용하라
73. 추상화 수준에 맞는 예외를 던지라
// 73-1 예외 번역
try {
... // 저수준 추상화를 이용한다.
} catch (LowerLevelException e) {
// 추상화 수준에 맞게 번역한다.
throw new HigherLevelException();
}
/**
* 이 리스트 안의 지정한 위치의 원소를 반환한다.
* @throws IndexOutOfBoundsException index가 범위 밖이라면,
* 즉 ({@code index < 0 || index >= size()})이면 발생한다.
*/
public E get(int index) {
ListInterator<E> i = listInterator(index);
try{
return i.next();
} catch (NoSuchElementException e) {
throw new IndexOutOfBoundsException("인덱스: " + index);
}
}
// 73-2 예외 연쇄
try {
... // 저수준 추상화를 이용한다.
} catch (LogwerLevelException cause) {
// 저수준 예외를 고수준 예외에 실어 보낸다.
throw new HigherLevelException(cause);
}
// 73-3 예외 연쇄용 생성자
class HigherLevelExcetion extends Exception {
HigherLevelException(Throwable cause) {
super(cause);
}
}
74. 메서드가 던지는 모든 예외를 문서화하라
75. 예외의 상세 메시지에 실패 관련 정보를 담으라
/**
* IndexOutOfBoundsException을 생성한다
*
* @param lowerBound 인덱스의 최솟값
* @param upperBound 인덱스의 최댓값 + 1
* @param index 인덱스의 실젯값
*/
public IndexOutOfBoundsException(int lowerBound, int upperBound, int index){
// 실패를 포착하는 상세 메시지를 생성한다.
super(String.format(
"최솟값: %d , 최댓값: %d, 인덱스: %d",
lowerBound, upperBound, index));
// 프로그램에서 이용할 수 있도록 실패 정보를 저장해둔다.
this.lowerBound = lowerBound;
this.upperBound = upperBound;
this.index = index;
}
76. 가능한 한 실패 원자적으로 만들라
public Object pop() {
**if (size == 0)
throw new EmptyStackException();**
Object result = elements[--size];
elements[size] = null; // 다 쓴 참조 해제
return result;
}
77. 예외를 무시하지 말라
// catch 블록을 비워두면 예외가 무시된다. 아주 의심스러운 코드다!
try {
...
} catch (SomeException e) {
}
Future<Integer> f = exec.submit(planarMap::chromaticNumber);
int numColors = 4; // 기본값. 어떤 지도라도 이 값이면 충분하다.
try {
numColor = f.get(1L, TimeUnit.SECONDS);
} catch (TimeoutException | ExecutionException ignored) {
// 기본 값을 사용한다(색상 수를 최소화하면 좋지만, 필수는 아니다).
}
반응형
'Java > EffectiveJava' 카테고리의 다른 글
[EffectiveJava] 12장 직렬화 (0) | 2023.02.24 |
---|---|
[EffectiveJava] 11장 동시성 (0) | 2023.02.24 |
[EffectiveJava] 9장 일반적인 프로그래밍 원칙 (0) | 2023.02.24 |
[EffectiveJava] 8장 메서드 (0) | 2023.02.24 |
[EffectiveJava] 7장 람다와 스트림 (0) | 2023.02.24 |