예외처리 (Exception Handling)

박대운·2022년 11월 10일
0

Java

목록 보기
5/9

예외처리 (Exception Handling)

예외처리란 예기치 않게 발생하는 에러에 대응할 수 있는 코드를 미리 사전에 작성하여 프로그램의 비정상적인 종료를 방지하고, 정상적인 실행 상태를 유지하기 위한 처리

프로그래밍에서 에러가 발생할 수 있는 몇가지 이유

  1. 사용자의 입력 오류
  2. 네트워크 연결 끊김
  3. 디스크 메모리 공간 부족 등 물리적 한계
  4. 개발자의 코드 에러
  5. 존재하지(유효하지) 않는 파일 불러오기

예시)

java: unreported exception java.io.FileNotFoundException; must be caught or declared to be thrown

존재하지 않는 파일을 불러올 때 이미 인텔리제이에서 컴파일 에러가 뜹니다.(빨간줄)

컴파일 에러

이름 그대로 컴파일할 때 에러가 발생하는 것을 말합니다.
인텔리제이에서는 미리 빨간줄로 컴파일이 되지 않게 알려줍니다.

런타임 에러

이것 또 한 이름 그대로 런타임시 에러가 발행하는 것을 말합니다.

public class RuntimeErrorTest {

    public static void main(String[] args) {
        System.out.println(4 * 4);
        System.out.println(4 / 0); // 예외 발생
    }
}

//출력값
16
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at RuntimeErrorTest.main(RuntimeErrorTest.java:5)

4를 0으로 나눌수 없다고 16은 출력 한 뒤 에러발생.

예외 클래스의 상속 계층도

출처. 구글이미지

모든 예외의 최고 상위 클래스인 Exception 클래스는 다시 크게 일반 예외 클래스와 실행 예외 클래스로 나눌 수 있습니다.

일반 예외 클래스(Exception)

런타임 시 발생하는 RuntimeException 클래스와 그 하위 클래스를 제외한 모든 Exception 클래스와 그 하위 클래스들을 가리킵니다.

컴파일러가 코드 실행 전에 예외 처리 코드 여부를 검사한다고하여 checked 예외라 부르기도 합니다.

주로 잘못된 클래스명(ClassNotFoundException)이나 데이터 형식(DataFormatException) 등 사용자편의 실수로 발생하는 경우가 많습니다.

실행 예외 클래스(Runtime Exception)

앞서 언급한 런타임 시 발생하는 RuntimeException 클래스와 그 하위클래스를 지칭합니다.

컴파일러가 예외 처리 코드 여부를 검사하지 않는다는 의미에서 unchecked 예외라 부르기도 합니다.

주로 개발자의 실수에 의해 발생하는 경우가 많고, 자바 문법 요소와 관련이 있습니다.

예컨대, 클래스 간 형변환 오류(ClassCastException), 벗어난 배열 범위 지정(ArrayIndexOutOfBoundsException), 값이 null인 참조변수 사용(NullPointerException) 등이 있습니다.

try - catch문

예외 처리란 잠재적으로 발생할 수 있는 비정상 종료나 오류에 대비하여 정상 실행을 유지할 수 있도록 처리하는 코드 작성 과정을 의미합니다.

예시)

public class RuntimeExceptionTest {

    public static void main(String[] args) {

        try {
            System.out.println("[소문자 알파벳을 대문자로 출력하는 프로그램]");
            printMyName(null); // (1) 예외 발생
            printMyName("abc"); // 이 코드는 실행되지 않고 catch 문으로 이동
        } 
        catch (ArithmeticException e) {
            System.out.println("ArithmeticException 발생!"); // (2) 첫 번째 catch문
        } 
        catch (NullPointerException e) { // (3) 두 번째 catch문
            System.out.println("NullPointerException 발생!"); 
            System.out.println("e.getMessage: " + e.getMessage()); // (4) 예외 정보를 얻는 방법 - 1
            System.out.println("e.toString: " + e.toString()); // (4) 예외 정보를 얻는 방법 - 2
            e.printStackTrace(); // (4) 예외 정보를 얻는 방법 - 3
        } 
        finally {
            System.out.println("[프로그램 종료]"); // (5) finally문
        }
    }

    static void printMyName(String str) {
        String upperCaseAlphabet = str.toUpperCase();
        System.out.println(upperCaseAlphabet);
    }
}

// 출력값
[소문자 알파벳을 대문자로 출력하는 프로그램]
NullPointerException 발생!
e.getMessage: null
e.toString: java.lang.NullPointerException
[프로그램 종료]
java.lang.NullPointerException
	at RuntimeExceptionTest.printMyName(RuntimeExceptionTest.java:20)
	at RuntimeExceptionTest.main(RuntimeExceptionTest.java:7)

null 이 예외발생했으니까 try-catch 문으로 가서 첫번째 ArithmeticException 이 아니니까 NullPointerException 실행.

한 가지 유의할 점은, 예외가 발생하면 catch 블럭은 위에서부터 순차적으로 검사를 진행하기 때문에, 구체적인 예외 클래스인 하위클래스를 먼저 위에 배치하여 상위 예외 클래스가 먼저 실행되지 않도록 방지하는 것이 좋습니다.

예외 전가

Throw 키워드로 예외를 다시 떠넘기기를 할 수 있습니다.

예시)

void ExampleMethod() throws Exception {
}

이 경우, Exception 클래스는 모든 예외 클래스의 상위 클래스이기 때문에 그 하위 클래스 타입의 예외 클래스들이 모두 포함되게 됩니다.

예시)

public class ThrowExceptionTest {

    public static void main(String[] args) {
        try {
            throwException();
        } catch (ClassNotFoundException e) {
            System.out.println(e.getMessage());
        }
    }

    static void throwException() throws ClassNotFoundException, NullPointerException {
        Class.forName("java.lang.StringX");
    }
}

//출력값
java.lang.StringX

먼저 try-catch 문 안에서 throwException 메서드가 호출되지만 잘못된 코드 작성으로 인한 런타임 에러가 발생합니다.

이렇게 예외가 발생한 경우, 앞서서 우리가 사용했던 예외 처리 방식은 잠재적으로 예외가 발생할 수 있는 곳에서 try-catch 문을 작성하여 예외처리를 해주었습니다.

하지만 위의 코드의 경우에는 앞서 설명한 것처럼 throws 키워드를 사용하여 해당 예외를 발생한 메서드 안에서 처리하지 않고 메서드를 호출한 곳으로 다시 떠넘기고 있습니다.

따라서 이제 예외처리의 책임은 throwException 메서드가 아닌 main 메서드가 지게 되었습니다.

profile
성장하는사람이 되자

0개의 댓글