프로그래밍을 하다보면 예기치 않은 오류를 만나기도 하고 심각하면 프로그램이 강제로 종료되기도 한다.
프로그램 오류의 원인으로는 크게 3가지로 나눌 수 있다.
논리 에러는 프로그램이 실행되는 데에는 전혀 문제가 없지만, 결과가 예상과 달라 사용자가 의도된대로 작업을 수행하지 못하는 문제이다.
예를 들어, 전진 키를 눌렀는데 우회전을 한다거나 피가 0이 되어도 죽지 않는다거나 하는 경우를 들 수 있다.
논리 에러는 컴퓨터 입장에서는 문제가 없기 때문에 에러 메시지를 알려주지 않는다.
논리 에러의 해결 방법은 프로그램의 코드와 알고리즘을 확인해보아야 한다.
컴파일 에러는 컴파일 단계에서 오류를 발견하여 에러 메시지를 출력하는 것을 말한다.
컴파일 에러의 대표적인 원인은 문법 오류(Syntax Error)이다.
예로, 문장의 끝에 세미콜론;을 생략했다거나 문자형으로 반환해야하는데 정수형으로 반환했을 경우이다.
컴파일 에러는 실행되기 전 컴파일 단계에서부터 걸러지기 때문에 심각한 문제는 아니고 오히려 미리 발견할 수 있기 때문에 다행인 오류이다.
런타임 에러는 프로그램이 실행되는 중에 발생하는 오류이다.
런타임 에러를 잘 다루어야 프로그램이 실행 중에 비정상적으로 종료되는 일을 막을 수 있다.

자바에서의 예외 상속 계층은 그림처럼 이루어져 있다.
Throwable 클래스는 모든 에러와 예외 클래스의 슈퍼 클래스이다.
이 클래스를 상속받은 객체들만 throw되어질 수 있기 때문에 모든 예외는 이 클래스를 상속받고 있다.
이 클래스에 정의된 두 메서드를 이용하면 예외 처리에 도움이 된다.
Exception 클래스는 그림에서 알 수 있듯이 RuntimeException(과 그 하위 클래스들)과 그 외의 클래스들로 나누어진다.
이 구분은 Checked Exception과 Unchecked Exception으로 볼 수 있다.
Checked Exception은 RuntimeException 클래스를 상속 받지 않은 Exception 클래스의 모든 하위 클래스를 말한다.
이름처럼 Checked Exception에 해당하는 클래스들은 무조건 예외에 대한 처리가 되어야 한다. 그렇지 않으면 컴파일 에러가 발생한다.
Unchecked Exception은 RuntimeException과 그 하위 클래스들을 말한다.
Checked와 Unchecked Exception의 중요한 차이가 있다.
Checked Exception 과는 반대로 예외에 대한 처리를 명시해줄 필요가 없다.
그렇다면 왜 Unchecked Exception은 예외 처리를 할 필요가 없을까?
public void main(String[] args) {
try {
int[] list = {1, 2, 3, 4, 5};
System.out.println(list[0]);
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}
}
이런 간단한 예시에서도 "배열의 범위를 넘어선 인덱스에 접근할 가능" 때문에 예외처리를 해야 한다면 불필요하게 복잡한 코드가 만들어질 것이다.
공식 문서에서도 이러한 이유가 나타나 있다.
1. Error 클래스는 기본적으로 핸들링이 불가능하기 때문에 처리를 명시할 필요가 없다.
2. RuntimeException 클래스가 발생시킬 수 있는 예외는 컴파일러가 모두 분석하기엔 불가능하고 그렇다고 모든 부분을 다 명시적으로 처리하기에는 코드가 깨끗하지 못하기 때문이다.