예외처리 (Exception Handling)

HYUNBIN CHO·2021년 7월 13일
0

java

목록 보기
22/23
post-thumbnail

🔷 예외처리

🔷 프로그램 오류

🔸 프로그램 실행 중 어떤 특정원인에 의해 정상적으로 작동하지 않거나 비정상적으로 종료가 되는 것을
프로그램 오류(에러)라고 한다.

🔸 프로그램 오류의 종류
- 컴파일 에러 : 프로그램 실행 전 컴파일 시 발생하는 에러
- 런타임 에러 : 프로그램 실행 시 발생하는 에러
- 논리적 에러 : 프로그램이 실행은 되지만, 프로그래머의 의도와 다르게 동작하는 에러

🔸 에러와 예외(런타임 에러)
- 에러 : 프로그램 코드에 의해 수습될 수 없는 오류 -> 일단 발생하면 복구할 수 없음, 비정상적인 종료를 막을 수 없음(심각한 것)
- 예외 : 프로그램 코드에 의해 수습될 수 있는 오류 -> 발생하더라도 적절한 대비 코드를 작성해 놓으면 비정상적인 종료를 막을 수 있음

🔷 예외 클래스 구조


Exception클래스들은 크게 RuntimeException과 그외 클래스들로 분류해 볼 수 있다.
🔸 RuntimeException클래스 : 프로그래머의 실수로 발생하는 예외
🔸 그외 Exception클래스들 : 사용자의 실수 등의 외부요인으로 발생하는 예외

또한 checked, unckecked Exception으로 나눌수 있다.
🔸 unchecked Exception :
       - 런타임 시점에서 확인하며,
       - 예외처리는 선택사항이다.
       - roll-back(O)
       - RuntimeException클래스와 자손들
🔸 checked Exception :
       - 컴파일 시점에 예외발생을 확인하며,
       - 반드시 예외 처리를 해야 한다.
       - roll-back(X)
       - RuntimeException클래스들를 제외한 Exception클래스들과 그 자손들
➡️ 만약 checked Exception이 발생할 가능성이 있는 메서드라면, try-catch문을 사용하거나 throw로 던져서 예외처리를 반드시 해줘야 한다.

🔷 예외처리 방법

🔸 예외처리란,
프로그램 실행 시 발생할 수 있는 예외의 발생에 대비해서 코드를 작성하는 것으로, 예외로 인한 프로그램의 비정상 종료를 방지하고 정상적인 실행상태를 유지하도록 하는 것

🔹 1. 예외처리하기

▪️ 1) try-catch

try{
    예외가 발생할 가능성이 있는 코드들
}catch(Exception1 e1){
    Exception1이 발생했을 때, 예외를 처리하기 위한 코드
}catch(Exception2 e2){
    Exception2이 발생했을 때, 예외를 처리하기 위한 코드
}

🔸 try블럭 내 코드를 수행하다가 예외가 발생하게 되면 여러개의 catch문장 중 발생한 예외와 같은 catch블럭 내 코드를 수행 후 try-catch문을 빠져나가서 다음 코드를 수행한다.
(만약 catch블럭에 같은 예외가 없으면 예외는 처리되지 못한다.)
🔸 try블럭 내에서 예외가 발생하지 않는다면, catch블럭을 거치지 않고 빠져나가서 다음 코드를 수행한다.

class Exception{
    public static void main(String args[]){
        int a = 100;
        int result = 0;
        for(int i = 0; i < 5; i++){
            try{
                result = a / (Math.random() * 10);
                // 랜덤값에서 0이 나오면 0으로 나눌 수 없으므로 ArithmaticException이 발생할 수 있음
                System.out.println(result);
            }catch(ArithmaticException ae){
                System.out.println("0");
            } // try-catch
        } // for
    }
}

🔸 printStackTrace() : 예외가 발생할 때 호출스택에 있었던 메서드의 정보와 예외 메시지를 출력한다.
🔸 getMessage() : 예외클래스의 인스턴스에 저장된 메시지를 얻을 수 있다.

try{
    ...
}catch(ArithmeticException ae){
    ae.printStackTrace();
    System.out.println(ae.getMessage());
}

▪️ 2) try-catch-finally

🔸 finally 블럭 : 예외 발생에 상관없이 실행되어야 하는 코드들을 넣는다

try{
    // 예외가 발생할 가능성이 있는 코드
}catch{
    // 예외처리를 위한 코드
}finally{
    // 예외 발생과 상관없이 항상 실행되어야 하는 코드
}

🔸 예외 발생 : try -> catch -> finally
예외 발생 안함 : try -> finally

▪️ 3) 예외 고의 발생시키기

🔸 throw 키워드를 사용하여 예외를 고의로 발생시킬 수 있다.
- new연산자를 이용, 예외클래스의 객체를 만든다
- throw키워드를 이용해서 예외를 발생시킨다.

try{
    Exception e = new Exception("예외 고의발생");
    throw e;
}catch(Exception e){
    System.out.println(e.getMessage());
    e.printStackTrace();
}

🔹 2. 메서드에 예외선언하기 : throws

🔸 메서드의 선언부에 throws 키워드를 이용해서 메서드 내에서 발생할 수 있는 예외를 적으면 된다.

void method() throws Exception{
    ...
}

➡️ 메서드를 사용하는 사람이 메서드를 사용할 때 어떤 예외가 처리되어야 하는지 쉽게 알 수 있다.
➡️ 엄밀히 말하자면, throws를 사용하여 예외를 적는 것은 예외처리하는 것이 아니라 '호출한 메서드에게 예외처리를 맡기는 것'이다.

class Test{
    public static void main(String args[]){
        try{
            method(); // 여기서 예외가 발생한 것으로 간주됨
        }catch(Exception e){
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }
    static void method() throws Exception{ 
    // method()에서 예외처리하지 않고 throws를 통해서 예외를 호출한 메서드로 넘긴다
        throw new Exception(); // 예외 고의로 발생
    }
}

🔸 주의점 : Exception(최고조상)을 예외선언하면 그 자손타입 예외까지 발생할 수 있다.
🔸 보통은 RuntimeException클래스들은 잘 적지 않는다.
🔸 메서드 내에서 자체적으로 처리가 가능한 것은 메서드 내에서 try-catch문을 통해 예외처리하고,
메서드 호출 시 값을 다시 넘겨 받아야 하는 경우에는 throws를 사용해 예외를 선언하고 호출한 메서드에서 처리한다.

🔹 예외 만들기

🔸 프로그래머의 필요에 따라서 원하는 예외를 정의하여 사용할 수 있다.

class MyException extends Exception{
    MyException(String msg){ // 문자열을 매개변수로 받는 생성자
        super(msg); // 조상클래스(Exception)의 생성자 호출
    }
}

🔹 예외 되던지기

🔸 예외가 발생한 메서드, 호출한 메서드 양쪽에서 처리할 수 있도록 하기 위해서 예외를 처리한 후, 다시 발생시키는 방법

class Test{
    public static void main(String args[]){
        try{
            method();
        }catch(Exception e){
            e.printStackTrace();
            System.out.println("main메서드에서 예외처리 됨.");
        }
    }
    static void method() throws Exception{
        try{
            throw new Exception();
        }catch(Exception e){
            System.out.println("method()에서 예외처리 됨.");
            throw e; // 예외 다시 발생
        }
    }
}
  1. main에서 method()가 호출된다.
  2. method()가 실행되면서 발생된 예외가 catch문에 걸려서 예외처리가 된 후, 다음코드(throw e)에 의해 다시 예외가 발생된다.
  3. 다시 발생한 예외로 인해 main에서 catch문에 예외가 걸려서 예외처리가 된다.
    🔸 return이 있는 경우 catch블럭에도 return이 있어야 한다.

🔹 연결된 예외

🔸 예외가 다른 예외를 발생시킬 수도 있다. (A예외가 B예외를 발생시켰다면, A는 B의 원인예외)
🔸 원인 예외를 새로운 예외에 등록한 후 다시 새로운 예외를 발생시키는데, 이를 예외 연결이라 한다.
🔸 연결 예외를 사용하는 이유 :
- 여러가지 예외를 하나의 큰 분류의 예외로 묶어서 다루기 위해서
- checked exception을 unchecked exception으로 바꿀 수 있도록 하기 위해서

SpaceException(원인예외)으로 InstallException 발생
try{
    startInstall(); // SpaceException 발생!
    copyFiles();
}catch(SpaceException se){
    InstallException ie = new InstallException("설치 중 예외 발생"); // 예외 생성
    ie.initCause(se); // ie의 원인예외로 se(SpaceException) 지정
    throw ie; // InstallException 발생
}catch(MemoryException me){
    ...
}

🔸 Throwable initCause(Throwable cause) : 원인예외로 등록
🔸 Throwable getCause() : 원인 예외를 반환

❖ Throwable은 Exception의 조상이므로 모든 예외에서 사용 가능함.

profile
백견이 불여일타

0개의 댓글

관련 채용 정보