본문 바로가기
[JAVA]/JAVA 기본

try - catch 문을 여러 경우의 수로 한 번에 이해해보자.

by 황원용 2023. 5. 24.
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

 

GitHub - wonyongg/test: test and summarize what i learned today.

test and summarize what i learned today. Contribute to wonyongg/test development by creating an account on GitHub.

github.com

 

728x90