이 글은 책 이펙티브 자바 3판 Item72과 하단 Reference 참고했습니다. 잘못된 내용이 있다면 편하게 말씀해주세요 🙏🏻
결론
자바 언어가 제공하는 표준 예외는 충분히 많다.
직접 만들지 말고 현재 상황에 맞는 표준 예외를 찾아 사용하자
이전 글 표준 라이브러리를 익히고 사용하자 에서 표준 라이브러리를 써야 하는 이유에 대해 알아봤다.
예외를 던질때도 마찬가지이다. 표준 예외를 사용하자.
왜?
- 읽기 쉬워진다.
- 메모리 사용량 감소, 클래스 적재 시간 감소, 예외도 직렬화에 포함되기 때문에 표준 사용이 좋다
자주 쓰이는 예외
예외 | 쓰임 | 예 |
IllegalArgumentException | 허용하지 않는 값이 인수로 건네졌을 때 (null일 때 써도 되지만 따로) | 나이를 나타내는 매개변수에 음수가 들어올 때 |
IllegalStateException | 객체가 메서드 수행하기에 적절하지 않은 상태일 때 | 제대로 초기화되지 않은 객체를 사용할 때 |
NullPointerException | 인수가 null일 때 | null값을 허용하지 않는 메서드에 null을 건넨 경우 |
IndexOutOfBoundsException | 시퀀스의 범위를 넘어섰을 때 | |
ConcurrentModificationException | 허용하지 않는 동시 수정이 발견됐을 때 | 단일 스레드에서 사용하려고 설계한 객체를 여러 스레드가 동시에 수정하려 할 때 |
UnsupportedOperationException | 호출한 메서드를 지원하지 않을 때 | 구현하려는 인터페이스의 메서드 일부를 구현할 수 없을 때 사용 List 구현체에 누가 remove 메서드를 호출할 때 던짐 |
단, 상위 예외 클래스(Exception, RuntimeException, Throwable, Error) 직접 사용하지 말자
상위 예외 클래스를 사용한다면, 예외 발생 시 구체적인 정보를 알 수 없다.
예제
IllegalArgumentException
허용하지 않는 값이 인수로 전달되었을 때의 경우 예외처리로 사용된다.
public class Person {
private int age;
public Person(int age) {
if (age < 0) {
throw new IllegalArgumentException("age는 음수를 허용하지 않습니다.");
}
this.age = age;
}
public static void main(String[] args) {
Person test = new Person(-3);
}
}
NullPointerException
인수가 null일 때
public class Person {
private Integer age;
public Person(Integer age) {
if (Objects.isNull(age)) {
throw new NullPointerException("age가 null 입니다.");
}
this.age = age;
}
public static void main(String[] args) {
Person test = new Person(null);
}
}
IndexOutOfBoundsException
시퀀스의 범위를 넘어섰을 때
public class CustomList {
List<Integer> list = new ArrayList<>();
public void add(Integer number){
if(list.size() > 4){
throw new IndexOutOfBoundsException("최대 저장 개수를 초과했습니다.");
}
System.out.println(list.size());
list.add(number);
}
public static void main(String[] args) {
CustomList list = new CustomList();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6); // IndexOutOfBoundsException 발생
}
}
UnsupportedOperationException
호출한 메서드를 지원하지 않을 때 예외를 발생시킨다.
아래 메인문 코드는 아무 문제없어 보이지만 UnsupportedOperationException예외가 발생된다.
public class UnsupportedOperationTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3);
list.add(10);
}
}
Exception in thread "main" java.lang.UnsupportedOperationException // 예외 발생
at java.base/java.util.AbstractList.add(AbstractList.java:153)
이유는 Arrays.asList()의 결과로 리턴된 list에 add() 메서드가 구현되어있지 않기 때문이다.
좀 더 자세히 보자면 정적 메서드 Arrays.asList()의 리턴 값은 Arrays 내부 inner class로 구현되어있는 ArrayList를 리턴한다. 이는 java.util.ArrayList와는 다르다. Arrays 내부 inner class의 ArrayList는 add, remove 등이 구현되어있지 않다. 따라서 List 인터페이스에서 add()가 오버 라이딩되어있지 않아 UnsupportedOperationTest 예외를 발생시킨다.
// 정정 메서드 Arrays.asList()의 소스코드
public static <T> List<T> asList(T... a) {
// 리턴 값 : ArrayList 이지만 java.util.ArrayList와 동일하지 않음, 아래 inner class 이다.
return new ArrayList<>(a);
}
/**
* @serial include
*/
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
// 내부 inner class 구현체 (생략)
// size, toArray, get, contains, indexOf, sort, iterator replaceAll 메서드만 오버라이딩 되어있다
}
⛓ Reference
https://stackoverflow.com/questions/5755477/java-list-add-unsupportedoperationexception
'☕️ JAVA > 🦋 Effective Java' 카테고리의 다른 글
매개변수가 유효한지 검사하기 (0) | 2022.03.21 |
---|---|
생성자에 매개변수가 많다면 빌더 패턴을 써볼까?! (HTTPClient와 lombok @Builder) 🧰 (0) | 2022.02.11 |
자바에서 객체 복사는 clone()이 아닌 복사 생성자, 팩토리를 사용하자 (0) | 2022.02.05 |
자바의 동시성 프로그래밍, 가변 데이터를 동기화하는 3가지 방법(+a. 자바 기본 타입의 원자성에 대하여) (0) | 2022.01.24 |
자바 enum에서 ordinal 메서드 사용하지마...(세요) 🚫 (1) | 2022.01.21 |
댓글