[스터디]Java의 정석 15일차

Kristopher·2022년 1월 10일
0

Java 스터디

목록 보기
15/31

(CH 8) 예외처리

프로그램 오류의 종류

프로그램 오류란 프로그램 실행 중 오작동하거나 비정상적으로 종료되는 경우를 말한다. 에러의 종류에는 발생 시점으로 구분하는 컴파일 에러와 런타임 에러, 그 외에도 논리적 에러 등이 존재한다.

컴파일 에러 : 컴파일 시에 발생하는 에러
런타임 에러 : 실행 시에 발생하는 에러
논리적 에러 : 실행는 되지만 의도와 다르게 동작하는 것

프로그램 에러가 발생하여 프로그램이 비정상적으로 종료되는 것을 막기 위해 적절한 예외처리를 취해 프로그램의 비정상적인 종료를 막을 수 있다. 해당 챕터에서는 예외처리의 종류와 방법에 대해 알아볼 예정이다.

예외 클래스의 구조

자바에서 발생 가능한 오류를 클래스로 정의하였다. 크게 Exception과 Error 클래스로 구분되며 Exception클래스 내부에서는 RuntimeException과 그 외로 구분한다.
RuntimeException클래스를 기준으로 Exception 클래스를 구분하는 이유는 RuntimException 클래스들은 프로그래머들의 실수에 의해 발생할 수 있는 예외이기에 프로그래밍 요소와 관련이 많다.(ex. 배열의 범위를 벗어난 경우, null인 참조변수의 멤버 호출, 형변환 실수 등) 그 외의 Exception 클래스들은 외부의 영향을 받아 발생하는 오류이다.(ex. 입력값이 올바르지 않은 경우 등)
컴파일러가 예외처리를 확인하지 않는 RuntimException 클래스들은 unchecked예외라고 부르고, 예외처리를 확인하는 Exception 클래스들은 checked예외라고 부른다.

try - catch문을 통해 예외처리하기

예외처리란 프로그램 실행 시 발생 가능한 예상하지 못한 예외의 발생을 고려하여 코드를 작성하는 것이다. 이를 통해 프로그램의 비정상 종료를 막고, 정상 실행상태를 유지할 수 있다.

try {
    // 예외가 발생할 수 있는 코드
} catch (Exception1 e1) {
    // Exception1이 발생한 경우 실행할 코드
} catch (Exception2 e2) {
    // Exception2가 발생한 경우 실행할 코드
}

try-catch문의 흐름은 다음과 같다. 먼저 try 블록 내부에서 예외가 발생한 경우 예외와 일치하는 catch 블록이 있는지 찾아 있으면 해당 클록이 실행되고 없으면 예외처리가 발생하지 않는다. try 블록 내부에서 예외가 발생하지 않으면 catch 블록을 실행하지 않고 try-catch문을 빠져나간다.

catch블록을 작성할 때 ()안에 선언된 참조변수의 타입과 예외클래스의 인스턴스에 instanceof 연산자를 이용해 검사하게 되는데 instanceof 연산자는 포함관계를 확인하는 연산자이므로 catch블록의 매개변수로 Exception을 넣게 되면 어떤 종류의 예외도 해당 블록에서 처리할 수 있다.

예외가 발생했을 때 생성되는 예외 클래스의 인스턴스에는 발생한 예외의 정보를 담고 있으며, 이 정보는 getMessage()와 printStackTrace()를 통해 확인할 수 있다.

Exception.printStackTrace() : 예외 발생 당시의 호출 스택에 존재하던 메소드의 정보와 예외 메세지를 화면에 출력
Exception.getMessage() : 발생한 예외 클래스의 인스턴스에 저장된 메세지를 반환한다.

멀티 catch 블록

여러가지 예외에 대해 같은 코드를 실행하고 싶다면 멀티 catch 블록형태를 사용할 수 있다. JDK 1.7이상부터 지원하는 기능이다.

try {
    ...
} catch (Exception1 | Exception2 e){
    e.printStackTrace();
}

위의 코드는 Exception1과 2에 대한 오류가 발생하면 catch블록에 의해 처리되는 코드이다. 다만 주의할 점은 Exception1과 2의 관계가 조상과 자손의 관계에 있다면 컴파일 에러가 발생하기 때문에 조상클래스만 써줘야 한다.

고의로 예외 발생시키기

throw를 사용해서 고의로 예외를 발생시키는 것이 가능하다.

  1. 발생시키고 싶은 예외 클래스의 객체를 만든다.
  • Exception e = new Exception("고의로 만든 예외");
  1. 키워드 throw를 사용하여 예외를 발생시킨다.
  • throw e;

메소드에 예외 선언하기

메소드 내에서 예외가 발생할 것 같을 때는 throws를 사용해 선언할 수 있다.

void method() throws Exception1, Exception2,... {
    //메소드 코드
}

throws를 통해 발생할 수 있는 예외를 선언하면 해당 메소드를 사용하려는 사용자가 메소드를 사용할 때 어떠한 예외처리를 고려해야하는지 알려줄 수 있다.
예외처리는 해당 메소드 내부에서 해결되지 못한 경우 자신을 호출한 메소드에게 전달할 수 있으며, 최종적으로 main 메소드에서도 처리되지 않으면 main 메소드가 종료되어 프로그램 전체가 종료된다.

class ExcepionEx {
    public statci void main(String[] args) throws Exception{
        method1();
    }
    
    static void method1() throws Exception {
        method2();
    }
    
    static void method2() throws Exception {
        throw new Exception();
    }
}

위 코드에서 main 메소드 -> method1() -> method2() 순서로 호출이 발생한다. 하지만 method2에서 예외가 발생하고 처리되지 못해 역순으로 전달되다가 main 메소드에서도 처리되지 못해 프로그램이 종료될 것이다.

finally 블록

finally 블록은 예외의 발생 여부에 상관없이 실행되어야 할 코드를 모아놓은 곳이다. try-catch문에 선택적으로 사용할 수 있으며 try-catch-finally순서로 구성된다.

try {
    // 예외가 발생할 가능성이 있는 코드
} catch ( Exception1 e1) {
    //Exception1이 발생한 경우 실행할 코드
} finally {
    //예외 발생과 상관 없이 수행해야할 코드
}

try-with-resources 구문

try-with-resources구문은 입출력 관련 클래스를 다룰 때 유용하다. 입출력시 사용하는 클래스는 사용후에 닫아 줘야 하는 것이 존재하는데, 닫는 과정을 거쳐야만 자원이 반환되어 불필요한 자원의 낭비를 막을 수 있기 때문이다.

try (File_Input_Stream fis = new File_Input_Stream("score.dat");
     Data_Input_Stream dis = new Data_Input_Stream(fis)){
         while(true) {
             ...
         }
} catch (Exception1 e1){
    ...
}

try-with=resources 구문은 try블록의 ()안에 객체를 생성하는 코드를 넣어 close()의 호출 없이 try문을 벗어나면 자동으로 close()가 호출되어 자원이 반환된다.

예외 되던지기(exceptoin re-throwing)

예외 되던지기란, 하나의 예외에 대해서 예외가 발생한 메소드와 호출한 메소드 양쪽에서 처리가 가능하도록 한 것이다. try-catch문을 통해 catch문에서 필요한 작업을 수행한 후 마지막에 다시 예외를 발생시켜 호출한 메소드에서 예외를 처리하도록 하는 것이다. catch문에서 인위적으로 예외를 발생시키므로 catch문을 포함하고 있는 메소드에서는 throws를 사용해야 한다.

연결된 예외(chained exception)

예외 A에 의해 예외 B가 발생한 상황이라면, 예외 A를 B의 원인 예외라고 한다. 발생한 예외를 그냥 처리하지 않고 원인 예외로 등록해서 다시 예외를 발생시키는 이유는 여러가지 예외를 하나로 묶어 다루기 위함이다. 또 다른 이유는 checked 예외를 unchecked로 바꾸어 억지로 예외처리를 해야하는 상황을 피할 수 있기 때문이다.

Reference

Java의 정석
남궁성의 정석코딩

profile
개발자 지망생입니다.

0개의 댓글