본문 바로가기

Develop/Java

Java Exception

728x90

Exception의 종류

2가지 분류가 존재합니다.

  1. Checked Exception: 컴파일 시점에 체크되는 Exception
  2. Unchecked Exception: 컴파일 시점이 아닌 런타임 시점에 체크되는 Exception

Exception 종류

연결된 예외의 처리

여러 예외 중 원인 예외를 지정해서 처리하는 방식입니다.

A예외가 B예외를 발생시켰다면 A예외를 원인 예외로 지정하는 방식입니다.

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

먼저, InstallException을 생성한 후에, initCause()로 SpaceException을 InstallException의 원인 예제로 등록합니다.
그 후 throw로 이 예외를 던집니다.

initCause()는 Exception클래스의 부모인 Throwalbe 클래스에 정의되어 있기 때문에 모든 예외에서 사용 가능합니다.

 

발생한 예외를 그냥 처리하지 않고 원인 예외로 등록해서 다시 예외를 발생시키는 이유는
여러가지 예외를 하나의 큰 분류의 예외로 묶어서 다루기 위해서입니다.


InstallException을 SpaceException과 MemoryException의 부모 예외로 catch 블럭을 작성하면
실제로 발생한 예외가 어떤 것인지 알 수 없는 문제가 생기며 SpaceException과 MemoryException의 상속 관계를 변경해야 합니다.

 

try {
	startInstall();
	copyFiles();
} catch (InstallException e) { // InstallException은 SpaceException과 MemoryException의 부모
	e.printStackTrace(); 
}

 

그래서 생각한 것이 예외가 원인 예외를 포함시킬 수 있게 한 것 입니다. 이렇게 하면,
두 예외는 상속관계가 아니어도 되며 Checked 예외를 Unchecked 예외로 바꿀 수 있도록 하기 위해서입니다.

Checked 예외로 예외처리를 강제한 이유는 프로그래밍 경험이 적은 사람도 보다 견고한 프로그램을 작성할 수 있도록 유도하기 위한 것인데 지금은 자바가 처음 개발되던 1990년대와 컴퓨터 환경이 많이 달라졌습니다.
그래서 Checked 예외가 발생해도 예외를 처리할 수 없는 상황이 하나둘 발생하기 시작했습니다.

이럴 때 할 수 있는 일이라곤 그저 의미없는 try-catch 문을 추가하는 것뿐인데
checked 예외를 unchecked 예외로 바꾸면 예외처리가 선택적이 되므로 억지로 예외처리를 안해도 됩니다.

 

// Checked 예외
static void startInstall() throws SpaceException, MemoryException {
	if (!enoughSpace()) // 충분한 설치 공간이 없으면...
		throw new SpaceException("설치할 공간이 부족합니다.");
	if (!enoughMemory()) // 충분한 메모리가 없으면...
		throw new MemoryException("메모리가 부족합니다.");
}
//원인 예외 등록해서 unchecked로 바꿈
static void startInstall() throws SpaceException {
	if(!enoughSpace()) // 충분한 설치 공간이 없으면...
		throw new SpaceException("설치할 공간이 부족합니다");
	
	if(!enoughMemory()) // 충분한 메모리가 없으면..
		// MemoryException을 원인 예제로 하는 RuntimeException 발생시킴(Unchecked)
		throw new RuntimeException(new MemoryException("메모리가 부족합니다."));
}

MemoryException은 Exception의 자식이므로 반드시 예외를 처리해야하는데
이 예외를 RuntimeException으로 감싸버렸기 떄문에 Unchecked 예외가 되었습니다.

그래서 더 이상 startInstall 메서드의 선언부에는 MemoryException을 선언하지 않아도 됩니다.
위의 코드에서는 initCause() 대신 RuntimeException의 생성자를 사용했습니다.