본문 바로가기

Java/Study

[JAVA] 백기선 라이브 스터디 9주차 예외처리

목표


자바의 예외 처리에 대해 학습하세요.

 

학습할 것


  • 자바에서 예외 처리 방법 (try, catch, throw, throws, finally)

  • 자바가 제공하는 예외 계층 구조

  • Exception과 Error의 차이는?

  • RuntimeException과 RE가 아닌 것의 차이는?

  • 커스텀한 예외 만드는 방법

 

자바가 제공하는 예외 계층 구조

 - 자바는 실행시 발생할 수 있는 오류를 클래스로 정의하였다.

자바의 예외 계층 구조

 

오류를 발생 시점에 따라 컴파일 에러, 런타임 에러, 논리적 에러로 분류 할 수 있다.

 

에러(Error)  : 프로그램 코드에 의해서 수습이 불가능한 심각한 오류
예외(Exception)  : 프로그램 코드에 의해서 수습이 가능한 오류

 


try-catch 오류

try부분에서 오류가 발생하면 객체가 생성되고, catch부분이 True가 되어 catch 블럭 아래의 코드가 실행됨

 


예외 발생 원인을  알기 위한 메소드

printStackTrace()   : 호출 스택에 있었던 정보와 예외 메세지 출력

getMessage()   : 발생한 예외 클래스의 인스턴스에 저장된 메세지

 

멀티 catch 블럭  - JDK1.7 하나의 catch블럭으로 합칠 수 있음

"|" 기호로 연결된 예외 클래스가 조상과 자손의 관계에 있으면 컴파일 에러가 발생함

 


Throw 예외

public class ThrowException {
    public static void main(String[] args) {
        try{
            Exception a = new Exception("오류 발생");
            throw a;
//          위 두줄과 같은 의미  throw new Exception ("오류 발생");
        }catch(Exception a){
            System.out.println("에러 메세지 " + a.getMessage());
//            a.printStackTrace();
        }
        System.out.println("--------------The End----------------");
    }
}

 

RuntimeException 클래스에 속하는 예외는 예외처리를 강제하지 않는다. -> unchecked예외

- 프로그래머가 실수로 발생하는 예외이다. 

만약 예외 처리를 해야 한다면?

아래와 같이, 참조 변수와 배열이 사용되는 모든 곳에 예외처리를 해야할 것이다. 

 

        try{
            int[] arr = new int[10];
            System.out.println(arr[0]);
        }catch(IndexOutOfBoundsException ie){
            
        }

 

Exception클래스와 그 자손들은 처리하지 않으면 컴파일조차 되지 않음

 

 


Throws 예외

메서드에 예외를 선언하는 방법

void method() throws Exception1, Exception2,...

메서드 내에 발생할 가능성이 있는 예외를 메서드의 선언부에 명시 -> 사용하는 쪽에서 처리를 강요

 

Exception 객체의 생성

코드상에서 try- catch구문을 수행하지 않으면 에러 발생!


finally 구문

예외 발생 여부와 상관 없이  실행.

try -> catch -> finally
try -> finally

커스텀한 예외 만드는 방법

 

 class MyException extends RuntimeException{
        // Exception 클래스를 안쓰는 이유: try -catch 문을 빼서 코드의 복잡성을 낮추기 위함
        MyException(String msg){ 
            super(msg); // 조상인 RuntimeException 클래스의 생성자를 호출한다.
        }

 

클래스 생성 방법과 동일하고 String msg를  Exception 클래스들에서 상속받는다.

Exception 클래스 혹은 RuntimeException 클래스를 상속 받는다.

public class CustomizeExceptionDemo {
    public static void main(String[] args) {
        try{// payMoney()가 Exception 클래스를 상속받으므로 try- catch문 안에 없을 시 에러 발생
            payMoney();
        }catch(LeakMoney LM){
            System.out.println("발생한 에러는:" + LM.getMessage());
        }catch (LeakPoint LP){
            System.out.println("발생한 에러는:" + LP.getMessage());
        }
    }

    public static void payMoney() throws LeakMoney, LeakPoint{
        if(!enoughMoney()){ throw new LeakMoney("잔액이 부족합니다.");}
        if(!enoughPoint()){throw new LeakMoney("포인트가 부족합니다.");}

    }

    private static boolean enoughPoint() {
        return true;
    }

    private static boolean enoughMoney() {
        return false;
    }

    class LeakPoint extends Exception{
        public LeakPoint(String message) {
            super(message);
        }
    }
    static class LeakMoney extends Exception{
        public LeakMoney(String message) {
            super(message);
        }
    }

}

이런식으로 하나의 메서드에 두 개의 에러를 발생시킬 수 있다.


 

※예외를  발생한 메서드와  호출한 메서드에서 양쪽으로 처리해야 할 경우 : exception re-throwing

 

public class re_Throwing {
    public static void main(String[] args) {
    // 호출한 메서드 내에서도 발생
        try{
            method();
        }catch(Exception e){
            System.out.println("main에서 예외가 처리 되었습니다.");
        }

    }
    static void method() throws Exception{
    //메서드 내 에서도 발생
        try{
            throw new Exception();

        }catch(Exception e){
            System.out.println("method 에서 예외가 처리 되었습니다.");
            throw e;
        }
    }
}

Chained exception

※   여러가지 예외를 하나의 분류로 만드는 방법  : 

                                                                     A를 B의 원인 예외(cause exception)으로 만든다 !

 

위의 CustomizeException 에 2가지 예외의 원인이 되는 예외를 생성한다.

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

 

InstallException을 상속받는 메서드를 추가한다.

    static void install() throws InstallException{
        try{
            payMoney();
        }catch(LeakMoney LM){
            InstallException ie = new InstallException("결제 중 예외 발생");
            ie.initCause(LM);
            throw ie;

        }catch(LeakPoint LP){
            InstallException ie = new InstallException("결제 중 예외 발생");
            ie.initCause(LP);
            throw ie;
        }
    }

Main문을 변경한다.

    public static void main(String[] args) {
        try{
            install();
        }catch(InstallException ie){
        
            ie.printStackTrace();
        }catch (Exception e){
        
            e.printStackTrace();
        }
    }