목표
자바의 예외 처리에 대해 학습하기
학습할 것
- 자바에서 예외 처리 방법(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 |