checked exception과 unchecked exception
checked exception과 unchecked exception에 대해서 설명해주세요.
checked exception과 unchecked exception에 대하여 설명을 하기에 앞서, 예외란 무엇일까요?
컴퓨터 과학에서 예외란 '프로그램 실행 중에 정상적인 프로그램의 흐름에 어긋나는 이벤트'를 예외라고 합니다. 이런 예외는 자바 코드가 실행되면서도 발생할 수 있습니다. 예를 들면 프로그램이 실행되는 중에 메모리가 부족해지거나 I/O 연산 중에 외부에서 에러가 발생하는 것 등이 있습니다. 이런 예외를 처리하고자 자바에서는 예외라는 객체를 통해서 프로그래머가 예외를 예상하고 핸들링을 할 수 있는 기능을 지원합니다. 이 부분을 일반적으로 다음과 같은 코드 블록에서 확인할 수 있습니다.
try {
//do something
} catch ( ExceptionType name ) {
} finally {
// clean up
}
자바에서는 위 코드와 같이 예외가 발생할 만한 코드 블록을 예외가 발생하지 않았을 때 로직과 발생했을 때 로직을 나누어서 설계할 수 있습니다. 이렇게 하면 다음과 같은 이점을 취할 수 있죠.
- 일반적인 코드와 에러 핸들링 코드를 나눌 수 있다.
- Call Stack으로 에러 발생을 전파할 수 있다.
- 에러 타입별로 그룹핑하고 구별하는 것을 할 수 있다.
그렇다면 객체지향 언어인 자바에서, 이 예외란 객체는 어떤 식으로 설계되었을까요? 우선 최상위 인터페이스로 Throwable이라는 인터페이스를 가집니다. 자바의 모든 예외 객체는 이 인터페이스를 직. 간접적으로 구현하기 때문에 자바에서 예외처리를 던진다, 잡는다.라고 표현을 합니다. 그리고 이 Throwable 인터페이스를 error와 exception 인터페이스가 구현을 하고, 다시 runtimeException이 exception 인터페이스를 구현합니다.
<출처 : http://www.javamadesoeasy.com/2015/05/exception-handling-exception-hierarchy.html>
여기서 한번 더 의문이 생깁니다. 왜 자바에서는 예외라는 객체를 이렇게 나누었고, 어떤 상황에 어떤 예외를 써야 하는가 입니다. 이 질문에 대한 답이 바로 unchecked Exception과 checked Exception의 차이이고, 존재 이유입니다. 그래서 Throwable은 구현한 Error와 Exception을 먼저 설명해보겠습니다.
error는 근본적으로 JVM에서 생성되거나, 나타나는 예외입니다. 이 말은 사용자 애플리케이션이 제어할 수 있는 예외가 아니라는 것이죠. 말 그대로 '에러'입니다. 애플리케이션의 범위를 벗어나기 때문에 대게 애플리케이션 단에서는 이 error를 처리하지 않습니다. 이 에러가 발생할 때 구동중인 애플리케이션은 죽는 게 맞는 거죠.
그래서 기본적으로 unchecked exception입니다. 이 에러가 발생한 코드나, 로직이나, 흐름에서 해당 에러를 처리할 수 없으니 차라리 확인하지 말고 무시해라입니다. 마지막에 JVM이 이 error를 확인해서 시스템 단에서 처리하라는 표시입니다.
e.g OutOfMemoryError
Exception 예외들은 '예상할 수 있는 예외'들입니다. 또는 '프로그래머가 만드는 예외'이기도 합니다. 이 Exception도 논리적으로 다음과 같이 두 개의 Exception으로 나뉩니다.
Checked exceptions은 프로그래머가 사용하는 라이브러리, 코드 등에서 new 생성자를 이용해 만들어졌고, 해당 모듈을 사용하는 오브젝트에게 여기서 예외가 발생할 수 있으니 throws 키워드를 이용해서 상위 caller에게 예외를 전달하든, 네가 확인해서 처리하든지 하라는 확인이 필요한 예외입니다. 다시 말하면, 컴파일 타임에 해당 예외가 체크되어야 하고, 프로그래머에게 예외를 다루거나 throws exception 같은 메소드를 선언할 것을 요구합니다. 예를 들어 FileNotFoundException과 같은 예외 객체가 있습니다.
Unchecked exceptions 또한 프로그래머 사용하는 라이브러리, 코드 등에서 만들어졌지만, 해당 모듈을 사용하는 오브젝트에게 여기서 발생한 예외를 확인해서 처리하라는 강제를 두지 않습니다. 예외는 발생할 수 있지만 필요 없거나 어차피 네가 처리하지 못할 예외니 그냥 상위 caller로 던지라 이 뜻입니다. 계속 던지다 보면 JVM이 받아서 프로그램을 종료하던가, 처리합니다. 대게 NullPointerException 같은 프로그래밍 에러로 나타납니다.
그리고 '프로그래머가 만드는 예외'라는 말은 우리도 코드를 만들면서 해당 예외를 생성하고 던지기도 합니다. 외부와 연결이 깨졌을 때, 메소드가 조작할 수 없는 비정상적인 상황을 맞았을 때, 미리 생성해둔 예외나 있는 예외를 throw new xxxException();으로 던지면 해당 메소드를 호출한 메소드에서 확인하거나 무시하거나 하는 것입니다.
그렇다면 Throwable 인터페이스를 구현한 여러 예외 객체들 중에서 어떤 것을 생성하고 던져야 하는 것일까요?
우선 error는 JVM을 위한 것이다. 그러니까 JVM에서 생성하는 예외입니다. 때문에 Exceptions을 사용하게 되는데,, 여기 Exception도 두개의 예외가 있습니다..
Checked vs unChecked
이 두 속성 중에 어느 것을 사용할 것인가에 대한 판단은 메소드를 호출한 객체가 해당 에러를 다룰 수 있는가를 판단하고, 가능하다면 checked, 아니면 unchecked 에러를 던집니다.
그리고 메소드를 호출한 객체는 예외를 처리할 수 있을 때, 혹은 다른 예외 타입으로 변경이 필요할 때 해당 예외를 try/catch 구문으로 잡아서 처리할 수 있습니다.
지금까지 봐왔던 예외는 자바의 안정적인 프로그램 설계에 있어서 필수이고, 제대로 된 예외 처리를 하는 프로그래머가 실력을 인정받기도 합니다.
http://javapeanuts.blogspot.kr/2012/02/exception-management-antipatterns.html