본문 바로가기

Java

예외 처리

훈수/저작권 관련 지적 환영합니다 - 댓글 또는 audgnssweet@naver.com

 

 

종류


에러 계층

자바에서 오류는

컴파일 시에 발생하는 컴파일 에러 (프로그램이 실행되지 않음)

실행 도중에 문제가 생겼을 때 발생하는 런타임 에러(프로그램이 종료됨)

이 있습니다.

원래 에러가 발생하면 프로세스가 종료됩니다.

 

그러나 프로그램이 반드시 종료되어야만 하는 경우가 아닐 때 (심각한 에러가 아닐 때)는

프로그래머가 직접 이런 오류를 handling 하여 원하는 처리를 할 수 있습니다.

 

예외와 에러 관계

런타임 에러 중 프로그래머가 컨트롤할 수 있는 것들을 예외라고 하고,

그렇지 않은 것들을 런타임 에러라고 합니다.

 

대표적인 런타임 에러로는 OutOfMemoryError가 있습니다. (메모리가 부족하면 어떤 방법으로든 해결이 안 되기 때문에 프로그램을 종료해야겠죠?)

 

대표적인 예외로는 ArithmeticException이 있습니다. (0으로 나누기를 하려고 할 때) 

이런 예외는 프로그래머가 다시 입력을 받는다던지 하는 방식으로 처리가 가능하겠죠?

물론 이런 예외들도 런타임 에러기 때문에, 프로그래머가 따로 처리를 하지 않는다면 프로세스가 종료됩니다.


 

 

 

try - catch (finally)


자바에서는 에러 처리를 할 때, try - catch 블록을 사용합니다.

try에는 에러가 발생할 가능성이 있는 코드들이 들어가고,

catch() 에는 발생 가능한 에러를 명시함으로써 에러 발생 후 뒤처리를 합니다.

 

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        int n1, n2, result;
        n1 = scanner.nextInt();
        n2 = scanner.nextInt();

        try {
            System.out.printf("%d / %d = %d", n1, n2, n1 / n2);  <- 에러 발생 가능 코드
        } catch (ArithmeticException e) {                        <- 처리할 에러 명시
            System.out.println("0으로 나눌 수 없습니다");
        } catch (Exception e) {
        	System.out.println("에러 발생");
        }
    }

위와 같이 catch를 여러 개 중첩시킴으로써 여러 개의 에러를 핸들링할 수 있습니다.

 

 

        try {
            System.out.printf("%d / %d = %d\n", n1, n2, n1 / n2);
            return 0;
        } catch (ArithmeticException e) {
            System.out.println("0으로 나눌 수 없습니다");
        } finally {
            System.out.println("프로그램 종료");
        }

여기서 finally는, 위의 try catch에서 에러가 발생하든 발생하지 않든 무조건 실행되는 코드입니다.

위의 try에서 return으로 프로그램을 종료한다고 해도, 종료되기 전에 finally 블록을 실행하고 종료합니다.


 

try-catch vs if-else


try-catch로 발생하는 에러를 '후처리' 한다면,

if-else로는 발생할 수 있는 에러에 대해서 선처리로 발생을 방지할 수 있습니다.

        if (n2 == 0) {
            System.out.println("0으로 나눌 수 없습니다");
        }else {
            System.out.printf("%d / %d = %d\n", n1, n2, n1 / n2);
        }

위와 같이 말이죠.

하지만 발생할 수 있는 에러의 종류가 많아지거나, 조건이 너무 많아지게 된다면 오히려 코드의 가독성을 해칠 수 있습니다.

 

만약 나눗셈 위에 else-if문이 5개 이상 붙어있다면 어떻게 될까요?

읽는 사람 입장에서 그 코드의 본 목적을 파악하기가 힘들 것입니다.

 

반면 try-catch에서 catch가 여러 개일지라도, 코드의 본 목적(핵심 로직) 은 맨 위 try 블록 안에 들어있기 때문에 그 코드의 목적을 명확하게 파악하기가 좀 더 쉽습니다.


 

 

에러 객체


자바에는 primitive type과 reference type이 있다는 것을 아실 것입니다.

그리고 대부분의 자료형은 reference type(객체)입니다.

이런 Exception도 마찬가지로 "객체" - 클래스입니다.

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        int n1, n2, result;
        n1 = scanner.nextInt();
        n2 = scanner.nextInt();

        try {
            System.out.printf("%d / %d = %d", n1, n2, n1 / n2);  <- 에러 발생 가능 코드
        } catch (ArithmeticException e) {                        <- 처리할 에러 명시
            System.out.println("0으로 나눌 수 없습니다");
        } catch (Exception e) {
        	System.out.println("에러 발생");
        }
    }

위의 클래스에서 ArithmeticException e 객체는 어떻게 생기는 것일까요?

맞습니다. JVM에서 에러가 발생하면, 해당 에러에 대한 여러 정보들을 객체로 매핑시켜 e라는 변수 안에 넣어주는 것입니다.

 

        } catch (ArithmeticException e) {
            System.out.println("0으로 나눌 수 없습니다");
            e.getMessage();
            e.getCause();
            e.getStackTrace();
        }

그래서 위와 같이 e 객체를 사용하면 우리가 직접 넣어주지 않았음에도 불구하고 여러 가지 정보를 얻을 수 있습니다.


 

 

자바의 에러 처리에 대해서 알아보았는데요,

에러 처리를 잘 한 프로그램일수록 안전성이 높아지므로

에러 처리에 대한 공부, 노력이 필요하겠습니다.

'Java' 카테고리의 다른 글

생성자  (0) 2021.04.13
클래스와 객체(미완성)  (0) 2021.04.06
자바 배열과 메모리  (0) 2021.03.30
레퍼런스 변수와 메모리, 에러  (0) 2021.03.30
Scanner로 키보드 입력 받기  (0) 2021.03.23