순간을 기록으로

[열혈자바] 18-1 자바 예외처리의 기본 본문

Development/JAVA

[열혈자바] 18-1 자바 예외처리의 기본

luminous13 2021. 10. 18. 11:54

개발을 하다보면 여러 상황에서 예상치 못하게 프로그램이 종료될 때가 있습니다. 이러한 상황은 예외처리라는 개념과 관련이 있습니다. 이번 시간에는 자바의 예외 처리에 대해서 알아보겠습니다.

 

먼저 '예외처리(Exception Handling)'가 무엇인지 배우기 예외가 무엇인지 알아보겠습니다. '예외(Exception)'란 예기치 못한 상황을 의미합니다. 즉 정상적이지 않은 상황을 뜻합니다. 말로 설명하는 것보다 코드로 보면 이해가 쉬우니 코드를 통해 설명하겠습니다.

 

import java.util.Scanner;

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

        int a = in.nextInt(); // 4
        int b = in.nextInt(); // 0

        System.out.println(a/b);  // 4 / 0
    }
}

위 프로그램은 2개의 숫자를 입력받아 나누기 연산을 해주는 프로그램입니다. 일반적으로 4 / 2 = 2, 6/2 = 3이 나오듯 잘 진행되지만 분모를 0으로 가질 경우에는 말 그대로 '예외적인 상황, 정상적이지 않은 상황'이 발생합니다. 기본적으로 JVM는 실행 중에 예외가 발생하면 예외의 원인과 행 위치, 어느 메소드에서 발생했는지 알려주고 프로그램을 종료합니다.

 

출력 결과를 보면 첫째 줄에서 예외 원인을 알려주고 둘째 줄에 행 위치와 어느 메소드에서 예외가 발생했는지 알 수 있습니다.. 예외 원인은 분모가 0으로 나누어서 이고, 예외 위치는 12행 main 메소드에서 발생했습니다.

 

일반적으로 JVM은 각 예외마다 예외클래스를 정의하고 있습니다. 예를들어 분모가 0과 같은 수학적 예외는 모두 ArithmeticException 클래스와 관련이 있습니다. JVM은 예외가 발생하면 관련 예외 클래스의 인스턴스를 생성하여 예외 원인과 위치를 알려주고 프로그램을 종료합니다.

 

하지만 만약 예외가 발생하더라도 프로그램을 종료시키지 않고 싶다면 예외를 처리하면 됩니다. 이를 예외처리라고 합니다. 예외처리는 try~catch 구문을 이용합니다. 

 

try{
	... 관찰 영역1...
    ... 관찰 영역2...
    ... 관찰 영역3...
}
chatch( Exception e ){
	... 예외 처리 영역
}

...다음 문장1...
...다음 문장2...

try 중괄호 안에는 예외가 발생할 수 있는 행들을 넣어줍니다.catch 부문에는 예외가 발생하면 어떻게 처리하겠다는 코드가 들어갑니다. catch는 메소드와 같이 동작합니다. 예를들어, 관찰 영역1에서 4/0을 하여 ArithmeticException 예외가 발생했다고 가정합시다. 그러면 JVM은 AirithmeticException 인스턴스를 만들어 catch 구문의 매개변수 e에 인스턴스를 전달합니다. 주의할 점은 관찰 영역 2에서 만약 예외가 발생한다면 관찰 영역3은 실행되지 않는다는 점입니다. 

 

 

import java.util.Scanner;

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

        try {
            int n1 = in.nextInt();
            int n2 = in.nextInt();

            System.out.println(n1 / n2);
        }
        catch(ArithmeticException e) {
            System.out.println(e.getMessage());
        }
        System.out.println("예외 처리 후 밑에 문장도 실행된다!!");
    }
}

매개변수 e는 예외 클래스의 인스턴스를 전달받습니다. 그리고 getMessage()를 호출하여 예외의 원인을 문자열로 받습니다.

 

 

Throwable 클래스와 예외처리 책임 전가

Throwable 클래스는 Object 클래스를 제외하고 예외 클래스의 최상위 클래스입니다. java.lang 패키지에 들어있고 Throwable 클래스에는 2가지 메소드가 정의되어있습니다.

 

  • public String getMessage()
    • 예외의 원인을 문자열로 반환
  • public void printStackTrace()
    • 예외의 위치(행 위치, 어느 메소드에서 발생했는지)를 추적하여 출력합니다.

JVM은 예외를 처리를 하지 않은 경우에는 getMeesage()를 호출시키고 printStackTract()를 호출합니다. 그리고 프로그램을 종료시킵니다.

코드를 통해 확인해보겠습니다.

 

public class ExceptionMessage {

    public static void main(String[] args){
        md1(3);	
        System.out.println("Good bye~~");
    }

    public static void md1(int n){
        md2(n, 0);      // 아래 메소드 호출
    }

    public static void md2(int n1, int n2){
        int r = n1 / n2;    // 예외 발생 지점
    }
}

 

위의 코드에서 md2()에서 예외가 발생하였고 원인은 분모가 0이었기 때문입니다. 이때 md2는 예외처리를 하지 않았는데 이렇게 예외가 발생한 메소드에서 예외처리를 하지 않을 경우 JVM은 예외가 발생한 메소드를 호출한 메소드에게 책예외처리 책임을 넘깁니다. 즉 md1()이 예외처리를 해야됩니다. 하지만 md1도 예외처리를 하지 않았기 때문에 md1()을 호출은 main()에게 책임이 전달됩니다. 하지만 main도 예외처리를 하지 않았기 때문에 JVM은 원인/위치 관련 메소드를 호출시키고 프로그램을 종료시킵니다. 

 

다음 편에는 예외상황을 알리기 위해 정의된 클래스의 종류와 예외 클래스 구조에 대해 알아보겠습니다.

Comments