글을 쓰게 된 계기
Assertions의 메서드들 중에는 다음과 같이 Exception을 테스트하는 메서드가 있다
<T extends Throwable> ThrowableTypeAssert<T> assertThatExceptionOfType(final Class<? extends T> exceptionType)
NotThrownAssert assertThatNoException()
ThrowableTypeAssert<NullPointerException> assertThatNullPointerException()
ThrowableTypeAssert<IllegalArgumentException> assertThatIllegalArgumentException()
ThrowableTypeAssert<IOException> assertThatIOException()
ThrowableTypeAssert<IllegalStateException> assertThatIllegalStateException()
assertThatExceptionOfType은 예외에 대해 포괄적으로 처리하는 메서드이고,
assertThatNoException은 예외가 발생하지 않는지 확인하는 메서드이다.
그리고 나머지 4개는 자주 사용하는 Exception에 대해 편의를 위해 만들어둔 메서드라고 한다.
자주 사용한다고 하니 이후에 만날 수도 있을 것 같았다. 그래서 이번 기회에 확실히 알아두면 좋을 것 같아 4가지의 예외를 정리해보려고 한다!
1. NullPointerException
public class NullPointerException extends RuntimeException {
...
}
예외의 이름을 보면 알 수 있듯이, null을 참조할 때 발생할 수 있는 예외이다.
이 경우 컴파일 시에는 에러가 발생하지 않고 Runtime에 발생한다.
void getNumberBetween1To10(int number) {
List<Integer> numbers = new ArrayList<>();
if (number == 1) {
numbers = null;
}
numbers.get(1);
}
다음과 같이 Runtime에 null이 될 수 있는 것을 참조한다면 null을 참조하였다는 예외가 발생할 수 있다.
(이 경우 컴파일 시에 잡아주지 않는다)
2. IllegalArgumentException
public class IllegalArgumentException extends RuntimeException {
...
}
IllegalArgumentException 또한 런타임에 발생할 수 있는 에러다.
적합하지 않거나, 적절하지 못한 인자를 메소드에 넘겨주었을 때 발생한다.
예를 들면 다음과 같은 상황에 발생한다
void getNumberBetween1To10(int number) {
if (number < 1 || number > 10) {
throw new IllegalArgumentException("1과 10 사이 숫자여야합니다");
}
}
1과 10 사이 값을 받아야하는데, 인자 단에서 확인할 방법이 없다.
그래서 메서드 안에서 검증을 수행하고, 적절한 값이 아닐 경우 IllegalArgumentException을 던진다.
3. IOException
class IOException extends Exception {
...
}
백준에서 BufferedReader를 많이 사용해본 사람이라면 자주 봤을 예외이다.
이 클래스는 실패하거나 중단된 I/O 작업으로 인해 발생하는 일반적인 예외 클래스입니다.
I/O가 실패할 경우에 발생할 수 있는 Exception이라고 한다. 사용자에게 입력을 받거나 출력할 때 발생할 수 있다.
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
br.close();
br.readLine();
}
다음과 같이 BufferedReader를 사용할 때는 IOException을 무조건 처리되어야한다.
중간에 BufferedReader가 닫힌상황에서 사용자의 입력을 읽으려고 할 때 IOException이 발생하게 된다.
4. IllegalStateException
public class IllegalStateException extends RuntimeException {
...
}
이 예외도 Runtime에 발생할 수 있는 예외이다.
설명을 읽어보면 다음과 같이 말한다
불법적이거나 부적절한 시간에 메서드가 호출되었음을 나타냅니다. 즉, Java 환경이나 Java 애플리케이션이 요청된 작업에 적합한 상태가 아닙니다.
메소드가 요구된 처리를 하기에 적합한 상태가 아닐 때 발생하는 예외라는데, 발생할 수 있는 상황을 보면서 어떤 예외인지 감을 잡아보자!
(1) Spring: Controller의 @RequestMapping의 값이 중복될 경우
@GetMapping("info")
public void test1() {}
@GetMapping("info")
public void test2() {}
(스프링부트에서 Controller로 요청을 받는 경우)
이 경우는 Controller의 RequestMapping이 동일한 2가지 경우가 있기 때문에 적절한 메서드를 찾을 수 없어 IllegalStateException이 발생한다고 한다.
이 상황을 보면 IllegalStateException은 input값으로 적절한 메서드를 찾을 수 없을 때 발생한다고 생각할 수 있다.
(2) 안드로이드에서 Fragment전환이 발생할 때
onSaveInstanceState()이 호출된 이후 Fragment 전환이 발생한다면, onSaveInstanceState()를 총해 결정되는 복구 시점과 다르게에 FragmentTransction에 대해서 복구할 수가 없다고 한다. 이런 상황이 발생한다면 사용자 경험(UX)를 해치는 결과를 초래하기 때문에 IllegalStateException을 던진다고 한다.
안드로이드에 대해 잘 모르지만, 맥락만 이해해본다면 도중에 상태가 바뀌어 원하는 결과값을 내놓을 수 없는 상황일 때 예외가 발생하게된다고 한다.
메서드를 수행하는 도중 상태가 변하여 적절한 결과값을 내놓을 수 없을 때 발생한다고 이해하면 될 것 같다.
(3) 자바 컴파일러가 2개의 다른 패키지에서 같은 이름의 클래스를 2개이상 찾을 때 발생
프로젝트를 임포트하고, 한 번에 두 클래스를 모두 가져올 때 해당하는 클래스를 찾을 수 없어 IllegalStateException이 발생한다고 한다.
(직접 해봤는데, 패키지가 달라도 클래스명이 중복되는 게 있으면 IDE에서 처리를 해줬다)
흔히 발생하는 상황은 아닌 것 같다.
이를 통해 IllegalStateException은 같은 이름의 클래스가 2개 있어 어떤 걸 선택해야하는지 모르는 상황에 발생하는 것을 알 수 있다.
(4) 동일한 ResourceReslover에서 다중 스레드를 사용했거나, 코드에서 열지않은 ResourceResolver 또는 javax.jcr.Session을 닫은 경우 발생
리소스를 동시에 변경하거나, 열지않은 걸 닫으려고 할 때 발생하는 것 같다.
(5) Steam<Object> 타입을 Map<String, Object>로 변환하는 과정에서 발생
class Student {
private String name;
public Student(String name) { this.name = name; }
public String getName() { return name; }
}
public class Main {
public static void main(String[] args) {
Student[] arr = {
new Student("연지"),
new Student("연지"),
new Student("마루"),
new Student("망곰")
};
Map<String, Student> map = Stream.of(arr)
.collect(Collectors.toMap(s -> s.getName(), p->p));
}
}
참고한 예시블로그: https://bada744.tistory.com/87
다음과 같이 stream을 사용하여 Map에 매핑할 때 key가 중복되는 경우 IllegalStateException이 발생한다.
이를 통해 IllegalStateException은 메서드를 수행할 때 정상적으로 동작할 수 없는 상황이라면 해당 예외를 던지는 것을 알 수 있다
정리해보면 IllegalStateException은 다음과 같은 상황에 발생한다
- 입력에 대해 2가지 동작이 수행될 수 있고, 어떤 걸 선택해야할 지 모를 때
- 메서드를 수행하는 도중 상태가 변하여 메서드가 적절한 결과값을 내놓을 수 없을 때
- 리소스를 동시에 변경하여 상태가 변경될 때
- 메서드를 수행할 때 입력값으로 정상적인 동작을 수행할 수 없을 때
그 외에도 부적절한 상황에 메서드가 호출될 때 사용될 수 있을 것 같다.
아직 IllegalArgumentException과 IllegalStateException이 조금 헷갈리지만, 맥락에 따라 잘 사용하다보면 익숙해질 수 있을 것 같다.
참고자료
https://goddaehee.tistory.com/126
[Java] NullPointException 원인, 예방, 해결하기
[Java] NullPointException 원인, 예방, 해결하기 안녕하세요. 갓대희 입니다. 이번 포스팅은 [ NullPointException 원인, 예방, 해결하기 ] 입니다. : ) 이번 회사 업무를 진행 하는 도중 별도의 과제를 받은 것
goddaehee.tistory.com
https://help.acmicpc.net/judge/rte/IllegalArgumentException
런타임 에러 (IllegalArgumentException)
Comparison method violates its general contract!Arrays.sort나 Collections.sort를 사용한 경우 Comparator가 다음을 지키지 않은 경우에도 발생합니다.모든 x, y에 대해서, sgn(compare(x, y)) == -sgn(compare(y, x))compare(x, y)가
help.acmicpc.net
https://it-hhhj2.tistory.com/95
[JAVA 에러] java.lang.IllegalStateException: Ambiguous mapping found.
문제상황 IllegalStateException 에러가 발생했다는 뜻 ... java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'performanceController' method ~~~해결방법 알고보니, Controller의 @RequestMapping 의 값이 중복되어 나타나
it-hhhj2.tistory.com
https://readystory.tistory.com/113
[Android] Fragment 전환 시 IllegalStateException 원인 및 해결
얼마 전에 플레이 스토어에 'Memory King' 이라는 간단한 게임을 올렸습니다. 늘 그렇듯 앱에 Crashlytics를 연동해두어 유저 측에서 비정상 종료가 발생했을 경우 해당 Error Log를 수신하도록 해두었는
readystory.tistory.com
java.lang.IllegalStateException: java.io.IOException: java.lang.reflect.InvocationTargetException 해결방법
프로젝트를 import하는 과정 중 이러한 에러가 발생하였다.맨앞의 에러명은 java.lang.IllegalStateException: java.io.IOException: java.lang.reflect.InvocationTargetException org.apache.tomcat.util.digester.Digester endElement SEVERE:
chrismare.tistory.com
로그에서 임의 "Resource Resolver가 이미 닫혔습니다."
이 문제는 동일한 ResourceResolver의 다중 스레드를 사용했거나 자체 코드에서 열지 않은 ResourceResolver 또는 javax.jcr.Session을 닫은 경우 발생할 수 있습니다.
helpx.adobe.com
https://bada744.tistory.com/87
[Java] Collectors.toMap() 변환 시 IllegalStateException 에러 발생 이유
에러 Stream 타입을 Map 로 변환하는 과정에서 IllegalStateException 예외가 발생한다. Student[] stuArr = { new Student("이자바", 3, 300), new Student("김자바", 1, 200), new Student("안자바", 2, 100), new Student("박자바", 2, 1
bada744.tistory.com
'프로그래밍 언어 > Java' 카테고리의 다른 글
IntelliJ java.util.concurrent.TimeUnit 이 없다고 나오는 에러(JDK21) (3) | 2024.10.26 |
---|---|
[JAVA] Test로 Collections 공부하기 (0) | 2023.11.07 |
[JAVA] 상수와 enum 공부하기2 (0) | 2023.11.07 |
[JAVA] 상수와 enum 공부하기1 (0) | 2023.11.07 |
[JAVA] 상수를 private static final로 선언하는 이유 (0) | 2023.11.07 |