728x90
try - catch - finally 문
try {
// 예외 발생 가능성이 있는 코드
}
catch (Exception1 e1) {
// Exception1 유형의 예외 발생 시 실행할 코드
}
catch (Exception2 e2) {
// Exception2 유형의 예외 발생 시 실행할 코드
}
finally {
// finally의 사용 여부는 옵션, 예외 발생 여부와 관게없이 항상 실행함.
}
try 안에 발생 가능성이 있는 Exception을 catch에 넣고 에러 발생 시 처리하는 테스트
private static void test1() {
/**
* 메서드 내 try 문에서 에러가 발생하고 catch에서 잡아 throw를 하지 않았기 때문에 그대로 넘어간다.
*/
System.out.println("-----------------------------------------");
System.out.println("<소문자를 대문자로 바꾸는 프로그램 - 첫번째 테스트>");
strToUpperCase(null); // 예외 발생하지만 메서드 내 catch에서 처리하고 끝.
System.out.println("-----------------------------------------");
try {
/**
* 메서드 내 첫번째 코드인 toLowerCase() 메서드에서 NullPointer 발생!!
*/
System.out.println("<대문자를 소문자로 바꾸는 프로그램 - 두번째 테스트>");
strToLowerCase(null); // 예외 발생
System.out.println("예외 넘어가는지 테스트"); // 여기까지 안옴
}
catch (ArithmeticException e) { // 예외적인 산술 조건인 경우 ex) 0으로 나누기 등
System.out.println("ArithmeticException입니다.");
}
catch (NullPointerException e) { // 넘겨주는 매개변수가 null인 경우
System.out.println("NullPointerException입니다.");
System.out.println("e.getMessage: " + e.getMessage()); // 예외 정보 출력
System.out.println("e.toString: " + e.toString()); // 예외 정보 출력
System.out.println("-----------------------------------------");
}
catch (Exception e) { //
System.out.println("Exception입니다.");
}
finally {
System.out.println("프로그램 종료");
}
}
static void strToUpperCase(String str) { // 테스트 메서드 1
try {
String upperCaseAlphabet = str.toUpperCase();
System.out.println(String.format("%s --> %s", str, upperCaseAlphabet));
}
catch (Exception e) {
System.out.println("첫번째 테스트 에러를 catch가 잡아 처리했습니다.");
};
}
static void strToLowerCase(String str) { // 테스트 메서드 2
String lowerCaseAlphabet = str.toLowerCase(); // 여기서 NullPointerException이 터지고 끝.
System.out.println(String.format("%s --> %s", str, lowerCaseAlphabet)); // 여기까지 안 옴
}
// 출력
-----------------------------------------
<소문자를 대문자로 바꾸는 프로그램 - 첫번째 테스트>
첫번째 테스트 에러를 catch가 잡아 처리했습니다.
-----------------------------------------
<대문자를 소문자로 바꾸는 프로그램 - 두번째 테스트>
NullPointerException입니다.
e.getMessage: null
e.toString: java.lang.NullPointerException
-----------------------------------------
프로그램 종료
- 첫번째 테스트의 경우 strToUpperCase 메서드의 인자에 null이 들어가 NullPointerException이 터지는데 이를 catch가 잡아 처리한다.
- 두번째 테스트의 경우 strToLowerCase 메서드의 인자에 null이 들어가 NullPointerException이 터진다.
- 이때 NullPointerException을 잡는 catch로 넘어갔기 때문에 catch 내의 코드를 실행하고 finally의 코드를 마지막으로 try - catch 문을 탈출한다.
- 만약 catch의 순서가 catch(Exception) -> catch(NullPointerException)이면 두번째 NullPointerException은 의미 없는 코드다.
- 첫번째 catch(Exception)에서 에러를 처리하고 try - catch문이 끝나기 때문이다.
- 애초에 인텔리제이에서는 오류가 뜬다.
static void strToUpperCase(String str) { // 테스트 메서드 1
try {
String upperCaseAlphabet = str.toUpperCase();
System.out.println(String.format("%s --> %s", str, upperCaseAlphabet));
}
catch (Exception e) {
System.out.println("첫번째 테스트 에러를 catch가 잡아 처리했습니다.");
throw new NullPointerException(); // 상위 메서드로 에러를 다시 던지기위해 에러 발생시킴
};
}
만약 위의 코드 중 테스트 메서드 1의 catch 문 안에 throw new NullPointerException();처럼 catch로 잡은 에러를 다시 던지는 방식을 사용하게 되면 에러가 발생한다.
try 안에서 고의적으로 예외를 발생시켜 catch에서 이후 로직을 처리하는 테스트
private static void test2() {
try {
// Some code that may throw a RuntimeException
System.out.println();
System.out.println();
System.out.println("-----------------------------------------");
int result = divide(10, 0); // 에러 발생
System.out.println("Result: " + result); // 위의 에러 발생으로 출력안함
} catch (RuntimeException e) {
System.out.println("Exception caught: " + e.getMessage());
System.out.println("-----------------------------------------");
e.printStackTrace();
}
}
public static int divide(int dividend, int divisor) {
if (divisor == 0) {
throw new ArithmeticException("Division by zero");
}
return dividend / divisor;
}
}
// 출력
-----------------------------------------
Exception caught: Division by zero
-----------------------------------------
BUILD SUCCESSFUL in 2s
2 actionable tasks: 1 executed, 1 up-to-date
java.lang.ArithmeticException: Division by zero
at org.example.Main.divide(Main.java:81)
at org.example.Main.test2(Main.java:70)
at org.example.Main.main(Main.java:6)
4:16:33 PM: Execution finished ':Main.main()'.
실무 사용 예시
case 1) 예외가 발생한 상황에 대해 문제점만 체크하고 메서드를 계속 진행시키고 싶은 경우
- catch 안에 system.out(), e.printStackTrace(), log.info() 등으로 로그만 남긴다.
case 2) 예외가 발생한 상황에 대해 로그를 남기고 메서드를 중지시키고 싶은 경우
- catch 안에 throw로 다시 예외를 발생시켜 메서드를 중지시킨다.
위 코드는 아래의 레파지토리에서 확인 가능하다.
https://github.com/wonyongg/test/tree/main/tryCatchTest
728x90
'[JAVA] > JAVA 기본' 카테고리의 다른 글
BindingResult에 대해 간단히 알아보기 (0) | 2023.06.13 |
---|---|
내부 클래스를 static으로 선언해야 하는 이유 (2) | 2023.06.09 |
JAVA + Spring Data JPA 프로젝트에 다중 DB를 연결해보자. (0) | 2023.05.23 |
DTO 클래스 ↔︎ Entity 클래스 Mapping에 대한 정리(ModelMapper, Mapstruct, 수동매핑) (0) | 2023.05.08 |
JVM과 자바 메모리 구조 간단 요약 정리 (0) | 2023.05.05 |