예외 처리(5) - 예외 되던지기, 연결된 예외
예외 되던지기(exception re-throwing)
앞서 말했던 것처럼 한 메서드에서 발생할 수 있는 예외가 여럿인 경우 몇 개는 try-catch문을 통해서 자체적으로 처리하고, 나머지는 선언부에 지정하여 호출한 메서드에서 처리하도록 함으로써 양쪽에서 나눠서 처리되도록 할 수 있다.
심지어 단 하나의 예외에 대해서도 예외가 발생한 메서드와 호출한 메서드 양쪽에서 처리하도록 할 수 있다.
- 이것은 예외를 처리한 후에 인위적으로 다시 발생시키는 방법을 통해서 가능한데, 이것을 예외 되던지기라고 한다.
먼저 예외가 발생할 가능성이 있는 메서드에서 try-catch문을 사용해서 예외를 처리해주고 catch문에서 필요한 작업을 행한 후에 throw문을 사용해서 예외를 다시 발생 시킨다
- 이 예외는 이 메서드를 호출한 메서드에게 전달되고 호출한 메서드의 try-catch문에서 예외를 또 다시 처리한다.
이 방법은 예외가 발생한 메서드와 이를 호출한 메서드 양쪽 모두에서 처리해줘야 할 작업이 있을 때 사용된다
- 주의) 예외가 발생할 메서드에서는 try-catch문을 사용해서 예외처리를 해줘야하는 동시에 메서드의 선언부에 발생할 예외를 throws에 지정해줘야 한다는 것이다.
class ExceptionEx17 {
public static void main(String[] args) {
try {
method1();
} catch (Exception e) {
System.out.println("main메서드에서 예외가 처리되었습니다.");
}
} // main메서드의 끝
static void method1() throws Exception { // re-throwing하는 경우 throws를 지정해줘야 한다
try {
throw new Exception();
} catch (Exception e) {
System.out.println("method1메서드에서 예외가 처리되었습니다.");
throw e; // 다시 예외를 발생시킨다.
}
} // method1메서드의 끝
}
반환값이 있는 return문의 경우 catch블럭에도 return문이 있어야 한다.
예외가 발생해도 값을 반환해야 하기 때문이다.
catch블럭에서 예외 되던지기를 해서 호출한 메서드로 예외를 전달하면 catch블럭에 return문이 없어도 된다
static int method1() {
try {
// ~~
return 0;
} catch (Exception e) {
e.printStackTrace();
// return 1; // catch블럭 내에서도 원래는 return문이 필요하다
throw new Exception(); // return문 대신 예외를 호출한 메서드로 전달한다.
} finally {
// ~~
}
}
연결된 예외(chained exception)
한 예외가 다른 예외를 발생시킬 수도 있다.
예외 A가 예외 B를 발생시켰다면, A를 B의 원인 예외(cause exception)이라고 한다.
try {
startInstall(); // SpaceException 발생
copyFiles();
} catch (SpaceException e) {
InstallException ie = new InstallException("설치 중 예외 발생"); // 예외 생성
ie.initCause(e); // InstallException의 원인 예외를 SpaceException으로 지정
throw iel // InstallException을 발생시킨다
} catch (MemoryException me) {
...
}
initCause()로 원인 예외를 등록한다
initCause()는 Exception 클래스의 조상인 Throwable클래스에 정의되어 있기 때문에 모든 예외에서 사용가능하다
왜 원인 예외로 등록해서 다시 예외를 발생시키나요?
원인1) 여러가지 예외를 하나의 큰 분류의 예외로 묶어서 다루기 위해서이다.
하나로 묶어서 다루기 위해 만약 catch의 참조변수에 부모 클래스 참조변수를 넣으면, 실제로 발생한 예외가 어떤 것인지 알 수 없는 문제가 발생한다.
그래서 예외가 원인 예외를 포함시킬 수 있게 한 것이다.
원인2) checked 예외를 unchecked예외로 바꿀 수 있도록 하기 위함이다.
예외를 RuntimeException으로 감싸버리면 unchecked 예외가 된다.
throw new RuntimeException(new MemoryException("메모리 부족"));
- initCause()대신 RuntimeException의 생성자를 사용할 수 있다.
이렇게 하면 더 이상 메서드의 선언부에 memoryException을 선언하지 않아도 된다.
Example 8.23
class ChainedExceptionEx {
public static void main(String args[]) {
try {
install();
} catch(InstallException e) {
e.printStackTrace();
} catch(Exception e) {
e.printStackTrace();
}
} // main메서드의 끝
static void install() throws InstallException {
try {
startInstall(); // 프로그램 설치에 필요한 준비를 한다.
copyFiles(); // 파일들을 복사한다.
} catch(SpaceException se) {
InstallException ie = new InstallException("설치 중 예외 발생");
ie.initCause(se);
throw ie;
} catch(MemoryException me) {
InstallException ie = new InstallException("설치 중 예외 발생");
ie.initCause(me);
throw ie;
} finally {
deleteTempFiles(); // 프로그램 설치에 사용된 임시파일들을 삭제한다.
} // try의 끝
} // install메서드의 끝
static void startInstall() throws SpaceException, MemoryException {
if(!enoughSpace()) { // 충분한 공간이 없으면
throw new SpaceException("설치할 공간이 부족합니다.");
}
if(!enoughMemory()) { // 충분한 메모리가 없으면
throw new MemoryException("메모리가 부족합니다.");
// throw new RuntimeException(new MemoryException("메모리가 부족합니다."));
}
} // startInstall메서드의 끝
static void copyFiles() { /* 파일들을 복사하는 코드를 적는다. */ }
static void deleteTempFiles() { /* 임시파일들을 삭제하는 코드를 적는다.*/ }
static boolean enoughSpace() {
// 설치하는데 필요한 공간이 있는지 확인하는 코드를 적는다.
return false;
}
static boolean enoughMemory() {
// 설치하는데 필요한 메모리공간이 있는지 확인하는 코드를 적는다.
return true;
}
} // ExceptionTest클래스의 끝
class InstallException extends Exception {
InstallException(String msg) {
super(msg);
}
}
class SpaceException extends Exception {
SpaceException(String msg) {
super(msg);
}
}
class MemoryException extends Exception {
MemoryException(String msg) {
super(msg);
}
}
참조) Java의 정석 3rd edition(남궁성, 도우출판)
'Programming Language > Java' 카테고리의 다른 글
[Java] 18. 불변 객체 (0) | 2024.10.15 |
---|---|
[Java] 17. Object 클래스 (0) | 2024.10.15 |
[Java] 15. 예외 처리(Exception handling)(4) - finally블럭, 자동 자원 반환: try-with-resources문, 사용자 정의 예외 (0) | 2024.07.09 |
[Java] 14. 예외 처리(Exception handling)(3) - 메서드에 예외 선언하기 (0) | 2024.07.09 |
[Java] 13. 예외 처리(Exception handling)(2) - try-catch 문 (0) | 2024.07.09 |