자바에서 예외를 Exception 이라고 한다.

 

프로그램의 예외란 무엇일까?

 

예외란 일반적인 실행이 아니라 예외적인 상황에서 실행되는 것을 의미한다.

 

컴퓨터에는 오류라는 개념이 있다. 예전에 인터넷에 많이 돌던 밈에는 윈도우 블루스크린 밈이 있다.

 

악명높은 블루스크린 화면

요새는 저런 스크린을 잘 보지 못하는 것 같다. 윈도우 과거 버전(95, xp 등)에서 빈번하게 발생하던 오류이다. 위에서 오류메시지를 보면

 

'치명적인 예외 상황이 발생했습니다. 현재 응용 프로그램은 종료합니다.'

 

여기서 말하는 Exception 이 예외적인 상황이 되었다는 것을 의미한다. 예외가 발생해서 더 이상 프로그램을 실행할 수가 없으니 종료합니다. 라는 뜻이다.

 

프로그램의 오류도 종류가 여러가지 있다. 컴파일시에 발생하는 컴파일 에러와 런타임에서 발생하는 런타임 에러가 있다. 이 중에서 error 라는 것은 좀 심각한 문제를 말하고 예외 exception 이란 것은 어느 정도 수습해서 프로그램을 지속할 수 있는 오류를 말한다. 예를 들어서 사용자가 숫자변수를 0으로 나누면 ZeroDivisionException  이 발생한다. 0으로 나누는 것은 허용이 안되지만 그렇다고 0 하나 때문에 전체 프로그램을 종료시키는 것도 효율적이지는 않을 것이다.

 

 

어느 정도 예측이 가능해서 수습할 수 있는 오류들을 다룰 수 있으면 프로그래밍이 훨씬 유연해진다. Exception 오류가 문법적인 오류는 아니다. 자바 컴파일러가 사전에 잡아낼 수 있는 오류를 다 잡고 나서도 실행시간에 일어나는 어쩔 수 없는 오류들이 있다. 그런 오류들을 처리하기 위해 자바는 Exception 이라는 클래스를 제공한다.

 

자바의 예외처리 try and catch 문 - 해보고 try 잡아라 catch

 

- 예외 클래스 : Exception (Java Platform SE 8 ) (oracle.com)

 

문법적으로는 try and catch 라는 블록을 사용해서 예외를 처리할 수 있다.

 

다음 예제코드는 예외 처리의 기본인 try catch 문을 사용한다. catch는 한개가 아니라 발생하는 예외의 종류에 따라 여러개도 가능하다. 

package com;

public class Main {

    public static void main(String[] args) {


        System.out.println("Try and Catch");

        try {
            int a = 10 /0;
            System.out.println("Try test");
        } catch (Exception e){
            System.out.println("Catch test");
        }
        System.out.println("process closed");
    }
}

 

 

마치 if else 구문과도 유사하게 try 나 catch 문 중 하나가 실행된다. 차이점은 try 구문의 어디에서 예외가 발생할지 모른다는 사실이다. 위에서는 zero divition error (0으로 나눔)이 발생한다. 예외가 발생하는 즉시 catch 문이 실행된다. 오류가 발생하면 프로세스를 종료시켜야 하는데 그렇지 않고 끝까지 실행이 완료되었다.

 

        System.out.println("Try and Catch");
        try {
            int a = 10 /0;
            System.out.println("Try test");
        } catch (ArithmeticException ae){
            System.out.println("-> AR exception");
        }
        System.out.println("process closed");

좀 더 세부적으로 계산 예외를 실행시켜봤다 Arithmetic Exception (산술 예외)

 

* 예외가 발생하면 JVM (자바가상머신)은 발생한 예외를 분석하여 알맞는 예외 클래스의 인스턴스를 생성한다. 구체적인 예외를 찾을 수 없으면 예외들의 조상인 Exception (일반 예외) 클래스까지 올라가기 때문에 어떠한 예외라도 다룰 수 있다. 이 때 사용하는 연산자가 instanceof (해당 객체의 인스턴스인지 판별) 이다.

 

 * 0으로 나누는 작업을 하면 Arithmetic Exception 의 인스턴스지만 이의 조상 클래스인 Exception의 인스턴스기도 하다. 어떤 예외가 발생할지 알 수 없다면 일반 예외 Exception 클래스를 사용할 수 있다. 물론 가능한 구체적인 예외를 예상하는게 디버그에 유리하다.

 

    public static void main(String[] args) {
        System.out.println("---- Try and Catch 예제 ---");
        try {
            int a = 10 /0; // 여기서 예외 발생
            System.out.println("Try test"); // 실행이 안된다.
        } catch (ArithmeticException ae){
            if (ae instanceof ArithmeticException)
                System.out.println("AR의 인스턴스가 맞다.");
            System.out.println("-> AR exception");
        } catch (Exception e){
            System.out.println("일반 예외 Exception");
        }
        System.out.println("--- process closed ----");
    }

예외처리에서 catch 를 여러개 사용함으로써 처리할 예외의 종류를 좁힐 수 있다.

 

위의 소스 코드는 AR 예외의 인스턴스임을 확인한다.

 

예외에 대한 정보

AR Exception 예외에 대한 정보는 JVM이 생성한 ae 인스턴스에 저장되어 있다. 이것도 클래스이기 때문에 Object로부터 상속받는 것은 같다. 자바는 예외 처리까지 객체지향 프로그래밍이 되어있다.

 

아래 코드에서는 AR Exception 에 대한 각종 정보를 출력해본다. 이런 메타데이터들이 처음에는 불필요하게 느껴지지만 나중에 가서는 자바언어의 시스템과 철학을 이해할 수 있는 바탕이 된다. 메타데이터가 많을 수록 JVM이 알아서 처리하고 있다는 것이니 프로그래머의 할일이 줄어든다.

    public static void main(String[] args) {
        System.out.println("---- Try and Catch 예제 ---");
        try {
            int a = 10 /0; // 여기서 예외 발생
            System.out.println("Try test"); // 실행이 안된다.
            
        } catch (ArithmeticException ae){
            if (ae instanceof ArithmeticException)
                System.out.println("AR의 인스턴스가 맞다.");
            
            System.out.println("-> AR exception printStackTrace, 마지막에 출력");
            ae.printStackTrace();
            System.out.println("예외 메시지 : " + ae.getMessage());
            System.out.println("로컬 메시지 : " + ae.getLocalizedMessage());
            System.out.println("toString : " + ae.toString());
            System.out.println("getStackTrace : " + ae.getStackTrace());

        } catch (Exception e){
            System.out.println("일반 예외 Exception"); // 실행이 안된다.
        }
        System.out.println("--- process closed ----");
    }

 

예외 catch 발생의 순서

아래와 같이 사용하면 catch는 한번만 실행된다. 여러개의 catch 문을 연결하면 try에서 발생한 첫번째 예외에 해당하는 예외처리가 일어나는 구조를 만들 수 있다. 맨 뒤에 catch (Exception e) 를 두면 다른 모든 예외들을 커버할 수 있으니 안전하다.

try {
    코드블록
} catch (ARException ae){
    코드블록
} catch (Exception e){
    코드블록
}

 

고의로 예외를 발생시키기

 

Exception 클래스와 throw 키워드로 고의로 예외를 발생시킬 수 있다. 테스트 등의 목적으로 사용한다.

    public static void main(String[] args) {
        System.out.println("---- Try and Catch 예제 ---");
        try {
            Exception e = new Exception("고의로 예외 발생시키기");
            throw e;
        } catch (Exception e){
            System.out.println("일반 예외 Exception");
            e.printStackTrace();
            System.out.println("메시지: " + e.getMessage());
            System.out.println("StackTrace: " + e.getStackTrace());
        }
        System.out.println("--- process closed ----");
    }

 

 

공유하기

facebook twitter kakaoTalk kakaostory naver band