본문 바로가기

Java 기본 문법 - 참조 서적 [이것이 자바다 - 한빛미디어]/8. 예외 처리

5. Java 자바 [예외 처리] - 사용자 정의 예외와 예외 발생 시키기, 예외 정보 얻기

 

 

자바 표준 API 에서 제공하는 예외 클래스만으로는 다양한 종류의 예외를 표현할 수 없다.

 

예) 은행 업무 처리에서 잔고 보다 많은 출금 요청 시, 오류!! 잔고 부족 예외는 표준 API에 존재하지 않는다.

 

 

어플리케이션 예외 : 개발자가 직접 정의해서 만들어야 하므로 사용자 정의 예외라고도 한다.

 


1. 사용자 정의 예외 클래스 선언

 

컴파일러가 체크하는 일반 예외로 선언하거나, 컴파일러가 체크하지 않는 실행 예외로 선언할 수 있다.

 

일반 예외로 선언 시 : Exception 상속

실행 예외로 선언 시 : RuntimeException 상속

 

형태

 

public class XXXException extends [ Exception | RuntimeException ] {

    public XXXException() { }                                                      // 생성자 두 개!

    public XXXException(String message) { super(message); }

}

 

 

- 사용자 정의 예외 클래스 이름은 Exception 으로 끝나는 것이 좋다.

 

- 사용자 정의 예외 클래스도 필드, 생성자, 메소드 선언을 포함할 수 있지만,

  대부분 생성자 선언만 포함한다.

 

- 생성자는 두 개를 선언하는 것이 일반적이다.

 

  하나는 매개 변수가 없는 기본 생성자

  다른 하나는 예외 발생 원인(예외 메시지)를 전달하기 위해 String 타입의 매개 변수를 갖는 생성자이다.

 

  예외 메시지의 용도는 catch{  } 블록의 예외 처리 코드에서 이용하기 위해서이다.

 

예) 잔고 부족 예외를 사용자 정의 예외 클래스로 선언

BalanceInsufficientException.java

 

public class BalanceInsufficientException extends Exception {
    public BalanceInsufficientException() {  }
    public BalanceInsufficientException(String message) {
        super(message);
    }
}

 

BalanceInsufficientException 은 Exception 을 상속하기 때문에 컴파일러가 체크 하는 예외(일반 예외) 이다.

따라서 소스 코드 작성 시 try - catch 블록으로 예외 처리가 필요하다.

 


2. 예외 발생시키기

 

사용자 정의 예외 또는 자바 표준 (API) 예외를 코드에서 발생시키는 방법

 

throw new XXXException();

throw new XXXException("메시지");

 

예외 객체를 생성 시 기본 생성자 또는 예외 메시지를 갖는 생성자 중 어떤 것을 사용해도 된다.

만약 catch 블록에서 예외 메시지가 필요하다면, 예외 메시지를 갖는 생성자를 이용해야 한다.

 

예외 발생 코드를 가지고 있는 메소드는 내부에서 try - catch 블록으로 예외 처리를 할 수 있지만,

대부분은 자신을 호출한 곳에서 예외를 처리하도록 throws 키워드로 예외를 떠넘긴다.

 

public void method() throws XXXException {

    throw new XXXException("메시지");

}

 

따라서 throws 키워드를 포함하고 있는 메소드는 호출 한 곳에서 아래와 같이 예외 처리를 해야 한다.

 

try {

    method();

} catch(XXXException e) {

    // 예외 처리 코드

}

 

예) 은행 계좌 클래스의 출금(withdraw) 메소드에서 잔고(balance) 필드와 출금액을 비교해서

잔고가 부족하면 BalanceInsufficientException 이 발생한다.

 

Account.java

 

public class Account {
    private long balance;
    public Account() {  }
    public long getBalance() {
        return balance;
    }
    
    public void deposit(int money) {
        balance += money;
    }
    
    public void withdraw(int money) throws BalanceInsufficientException {   // 예외 떠넘기기
        if(balance < money) {
            throw new BalanceInsufficientException("잔고 부족! :"+ (money - balance) + "모자람");
        }
        balance -= money;
    }
}

 


3. 예외 정보 얻기

 

try 블록에서 예외가 발생하면, 예외 객체는 catch 블록의 매개 변수에서 참좋라게 되므로

매개 변수를 이용하면 예외 객체의 정보를 알 수 있다.

 

모든 예외 객체는 Exception 클래스를 상속하기 때문이다.

따라서 Exception 이 가지고 있는 메소드들은 모든 예외 객체에서 호출할 수 있다.

 

 

자주 사용되는 메소드

getMessage(), printStackTrace()

 

예외를 발생시킬 때 아래와 같이 String 타입의 메시지를 갖는 생성자를 사용하면, (예외 객체 생성)

메시지는 자동적으로 예외 객체 내부에 저장된다.

 

throw new XXXException("예외 메시지");

 

예외 메시지에는 왜 예외가 발생했는지에 대한 간단한 설명이 포함된다.

상세한 원인을 세분화하기 위해 예외 코드를 포함하기도 한다.

 

예) 데이터베이스에서 발생한 오류들은 예외 코드가 예외 메시지로 전달된다.

이와 같이 예외 메시지는 아래와 같이 catch 블록에서 getMessage() 메소드의 리턴값으로 얻을 수 있다.

 

} catch(Exception e) {

    String message = e.getMessage();

}

 

printStackTrace()는 예외 발생 코드를 추적해서 모두 콘솔에 출력한다.

어떤 예외가 어디서 발생했는지 상세하게 출력한다. (디버깅 시 이용)

 

printStackTrace

 

예) AccountExample 클래스는 Account 클래스를 이용해서 예금 / 출금을 한다.

     출금 시 withdraw() 메소드를 사용하므로 꼭 예외 처리가 필요하다.

 

     예외 처리 코드에서 BalanceInsufficientException 객체의

     getMessage() 메소드와 printStackTrace() 메소드로 예외에 대한 정보 얻고 있다.

 

AccountExample.java : 실행 클래스

 

public class AccountExample {
    public static void main(String[] args) {
        Account account = new Account();

        // 예금하기
        account.deposit(10000);   // 10000원 입금
        System.out.println(“예금액 : ”+ account.getBalance());

        // 출금하기
        try {
            account.withdraw(30000);   // 30000원 출금
        } catch(BalanceInsufficientException e) {  // 예외 메시지 얻기
            String message = e.getMessage();
            System.out.println(message);
            System.out.println();
            e.printStackTrace();    // 예외 추적 후 출력
        }
    }
}

 

[출력 결과]

예금액: 10000

잔고부족: 20000 모자람

 

“잔고부족: 20000 모자람” 은 getMessage() 메소드의 리턴값을 출력한 것이다.

 

printStackTrace() 메소드에 의해 출력된 내용을 보면

Account.java 에서 발생된 예외가 AccountExample.java 의 메소드 호출 위치로 예외가 떠넘겨진다.