본문 바로가기

Java Live Study

Live Study 9주차 : 예외 처리

목표

자바의 예외 처리에 대해 학습하기

 

학습할 것

  • 자바에서 예외 처리 방법(try, catch, throw, throws, finally)
  • 자바가 제공하는 예외 계층 구조 ->최상위throwable -> 그 밑에 exception, error
  • Exception과 Error의 차이는?
  • RumtimeException과 RE가 아닌 것의 차이는?
  • 커스텀한 예외 만드는 방법

 


 

 

예외란? 컴파일 시 발생하는 문법적인 에러가 아니라, 프로그램 실행 도중 발생하는 예기치 않은 문제

  • 정수를 0으로 나누는 경우
  • 배열의 첨자가 음수값을 가지는 경우
  • 배열의 첨자가 배열의 크기를 벗어나는 경우

 

 

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

 

try~catch

  • 자바에서는 예외처리를 위해 try~catch문을 제공한다
    • try : 예외상황이 발생할만한 영역을 감싸는 용도로 사용
    • catch : 발생한 예외의 처리를 위한 코드를 묶어두기 위한 용도로 사용
  • catch에서 예외상황이 처리되기 때문에 소스코드상에서는 예외처리를 위한 코드를 쉽게 구분 가능
  • try~catch 사이에 다른 문장이 삽입될 수 없음

 

try{
    // todo
    // try 영역에서 발생함 예외상황은
}
catch(IllegalArgumentException e){
    // 이어서 등장하는 catch 영역에서 처리한다
    // 여러개의 catch문을 사용할 때, 가장 좁은 그물망을 위에
}
catch(RuntimeException e){
    // 다음으로 넓은 그물망
}
catch(CCC e){
}

 

 

0으로 나누는 예외상황이 발생한다면?

- try 영역에서 ArithmeticException이라는 클래스가 의미하는 예외상황이 발생하면 그 다음 catch 영역에 의해 처리 된다

- catch 영역에서 적절한 대처를 하는 것은 프로그래머의 몫

 

흐름은 다음과 같다.

1. JVM이 0으로 나누는 예외상황이 발생함을 인식

2. 이 상황을 위해 정의된 ArithmeticException 클래스의 인스턴스를 생성

3. 이렇게 생성된 인스턴스의 참조 값을 catch 영역에 선언된 매개변수에 전달

 

class DivideByZero{
    public static void main(String args[]){
        try{
            System.out.println("나눗셈 결과 : " + 7/0);
        }
        catch(ArithmeticException e){
            System.out.println("나눗셈 불가");
            System.out.println(e.getMessage());
        }
        
        System.out.println("프로그램 종료");
    }
}

/* output
나눗셈 불가
/ by zero
프로그램 종료
*/

 

 

finally : 예외상황의 발생여부와 상관없이 항상 실행되는 영역

예외상황의 발생여부에 상관없이 항상 실행되어야 하는 코드도 존재한다.

즉 finally 구문은 실행의 흐름이 try 영역으로 진입하면, try~catch문을 빠져나가는 마지막 순간에 무조건 실행되는 영역이라고 이해하면 된다.

 

 

throw :  예외 상황이 발생되었음을 JVM에 알리는 키워드

throw문이 존재하는 부분이 try~catch로 감싸지 않고 있다면, 예외 처리는 throw문이 존재하는 메소드를 호출한 영역으로 넘어간다.

그래서 아래 예제에서 readAge()를 호출한 문장을 try~catch로 감싸주었다.

 

 

throws : 메소드를 호출한 영역으로 예외가 전달되도록 하는 키워드

 

 

 

point 1) 예외상황이 메소드 내에서 처리되지 않으면, 메소드를 호출한 영역으로 예외의 처리가 넘어감을 명시해야 함

point 2) throw에 의해 생성된 예외상황은 반드시 try~catch문에 의해 처리되거나 throws에 의해 넘겨져야 함

 

class AgeInputException extends Exception{
    public AgeInputException(){
        super("유효하지 않은 나이가 입력됨");
    }
}

class ThrowsFromMain{
    public static void main(String args[]){
        try {
            int age = readAge(); // throw에 의해 이동된 예외처리 포인트
            System.out.println("당신의 나이는 " + age + "세 입니다.");
        } catch (AgeInputException e) {
            System.out.println(e.getMessage());
        }
    }
    
    public static int readAge() throws AgeInputException{
        int age = -1;
        if(age<0){
            AgeInputException excpt = new AgeInputException();
            throw excpt; // 예외처리 포인트
        }
    
        return age;
    }
}

 


 

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

 

  • 자바는 예외, 즉 오류도 객체로 취급한다.
  • 자바에서는 발생할 수 있는 에외에 대하여 java.lang 패키지에 예외 관련 클래스를 제공한다.
  • 자바의 모든 예외 관련 클래스는 java.lang.Throwable 클래스의 하위 클래스로 제공 된다.
  • Throwable를 상속하는 예외 클래스는 Exception과 Error 두 가지이다.
    • Error 클래스는 주로 하드웨어 관련 예외 처리하는 클래스

 

예외클래스 계층도

 

 

 

 

 


 

 

Exception과 Error의 차이는?

 

 

 

Error

  • 단순히 예외라기보다, 심각한 오류의 상황을 표현하기 위해 정의된 클래스.
  • 이 클래스를 상속하여 정의된 클래스는 프로그램의 실행을 멈춰야 할 정도의 심각한 오류 상황을 표현한다.
  • Error를 상속하는 대표적인 클래스는 VirtualMachineError 클래스(자바 가상머신에 문제가 생겨 더 이상 제대로 동작할 수 없는 상황을 알리기 위해 정의된 클래스)가 있다.
    • 자바 가상 머신이 더 이상 실행될 수 없는 상황에서 프로그래머는 할 수 있는 특별한 조치가 없으며 try~catch로 해결할 수 없다.
    • 따라서 Error를 상속하는 클래스의 오류 상황이 발생하면 프로그램이 종료되도록 놔두는 것이 낫다. (코드를 수정하자.)

 

그렇기에 Error보다는 Exception 에 더 관심을 두어야 한다.

 

 

Exception

  • 결과적으로 Exception은 모든 예외 클래스의 상위 클래스이다.
  • 예외 클래스를 정의하는 과정에서 Exception 클래스를 상속하였고, 때문에 throw의 대상이 될 수 있었다.
  • 참고로 Exception을 직접 상속하는 예외 클래스는 약 100여개 정도 된다.

 

 


 

 

RumtimeException과 RumtimeException가 아닌 것의 차이는?

 

 

  • Exception의 하위 클래스 중에 RuntimeException 클래스가 존재하며, 이 클래스는 Error 클래스와 비슷하다.
  • RuntimeException을 상속하는 예외 클래스도 Error를 상속하는 예외 클래스와 마찬가지로 try~catch문, throws절을 이용한 예외처리를 필요로 하지 않는다. -> 예외 지정에 소요되는 노력이 예외를 지정하여 얻는 효율보다 더 크기 때문에
  • RuntimeException과 Error 클래스를 제외한 나머지 클래스와 관련된 예외는 프로그램에서 처리하도록 요구.
    • 예를 들어 입출력과 관련된 예외들은 프로그램에서 직접 처리하도록 요구하고 있으며, 관련 예외 처리를 지정하지 않으면 컴파일러 오류 발생

 

 

하지만

  • RuntimeException을 상속하는 예외 클래스는 Error를 상속하는 예외 클래스처럼 치명적인 상황이 아님
  • 따라서 예외발생 이후에 실행의 흐름을 이어가기 위해 try~catch문으로 해당 예외를 처리하기도 함

 


 

커스텀한 예외 만드는 방법

 

기존에 있는 예외를 사용할 수 있으면 그것을 사용하면 되고

그 외 자바가 제공하는 예외 클래스만으로 모든 예외를 커버하기 어려울 때, 직접 정의하여 사용할 수 있다.

 

 

 

class AgeInputException extends Exception{
    public AgeInputException(){
        super("유효하지 않은 나이가 입력됨");
    }
}

class ThrowsFromMain{
    public static void main(String args[]){
        try {
            int age = readAge(); // throw에 의해 이동된 예외처리 포인트
            System.out.println("당신의 나이는 " + age + "세 입니다.");
        } catch (AgeInputException e) {
            System.out.println(e.getMessage());
        }
    }
    
    public static int readAge() throws AgeInputException{
        int age = -1;
        if(age<0){
            AgeInputException excpt = new AgeInputException();
            throw excpt; // 예외처리 포인트
        }
    
        return age;
    }
}

 


 

참고

  • 처음 시작하는 JAVA 프로그래밍, 김충석 저
  • 난 정말 JAVA를 공부한 적이 없다구요, 윤성우 저

'Java Live Study' 카테고리의 다른 글

Live Study 13주차 : I/O  (0) 2021.03.05
Live Study 12주차 : 애노테이션  (0) 2021.02.06
Live Study 8주차 : 인터페이스  (0) 2021.01.16
Live Study 7주차 : 패키지  (0) 2021.01.02
Live Study 6주차 : 상속  (0) 2020.12.26