프로그램을 작성할 때 문법에 맞지 않게 작성하고 컴파일하거나 또는 어떤 원인에 의해서 예상치 못한 에러가 발생할 수 있습니다. 이러한 의도하지 않은 상황에 대해서 처리하기 위해 예외(Exception)를 제공합니다.
예외(exception)는 에러가 발생하여 실행중인 프로그램이 비정상적으로 종료되지만 다음과 같은 예측 가능하여 처리할 수 있도록 설계할 수 있는 것을 말하며, 자바에서는 try-catch문을 통해서 예외를 처리할 수 있는 문법이 존재합니다.
에러는 발생 시점에 따라서 크게 3가지로 나눌 수 있습니다.
컴파일 에러는 말 그대로 소스코드(*.java)를 컴파일 할 때 발생하는 에러로 오타 혹은 문법적으로 잘못된(세미콜론 생략, 잘못된 자료형 등) 구문들, 보통 문법적인 문제를 가리키는 에서 에러가 있을 때 발생합니다. 컴파일 에러를 신택스 에러(Syntax Error)라고 부르기도 합니다.
컴파일 에러는 자바 컴파일러가 오류를 감지하여 사용자에게 알려줍니다. 보통 IDE에서 입력하다가 구문에러가 발견되면 즉시 빨간줄로 그어 사용자에게 미리 알려주기 때문에 발견하기도 쉽고 사전에 방지 할 수 있습니다.
이 과정을 거쳐서 컴파일 시 컴파일 에러가 발생하지 않고 성공적으로 수행을 마치면 소스코드파일은 컴파일러를 통해 클래스(*.class)파일을 생성하고 실행할 수 있게 됩니다.
런타임 에러는 프로그램이 실행도중 발생하는 에러를 말합니다. 보통 실행 중에 어떤 원인에 의해 잘못된 결과값을 얻거나 비정상적인 종료, 혹은 멈춘상태의 지속 등의 경우가 런타임 에러에 해당합니다.
public static void main(String[] args) {
System.out.println(2 % 0);
}
/* ====== result ======
Exception in thread "main" java.lang.ArithmeticException: / by zero
======================= */
런타임에러는 위의 예제와 같이 문법상의 에러는 없지만 컴퓨터가 더이상 해당 구문을 수행할 수 없어 프로그램이 비정상적으로 종료되고 에러메세지를 띄워줍니다. 위의 예제에서는 ArithmeticException이 발생한 것을 확인할 수 있습니다.
런타임 에러는 프로그램이 실행될 때 JVM에서 감지되며 메모리 부족(OutOfMemoryError)이나 스택오버플로우(StackOverflowError) 등 발생하면 복구할 수 없는 것을 에러, 그리고 예외현상을 예측하고 대응코드를 작성할 수 있는 비교적 덜 심각한 에러를 예외라고 합니다.
자바에서는 예외와 오류를 클래스로 정의해두었습니다. 자바는 예외가 발생하면 클래스에서 인스턴스화를 통해 예외처리를 진행합니다.
위의 그림은 예외 클래스의 상속 계층도 입니다. 예외(Exception)의 최상위 클래스는 Exception클래스 인 것을 확인할 수 있습니다. 여기서 예외의 최상위 클래스 Exception클래스는 RuntimeException과 다른 일반 예외 클래스들이 존재합니다.
일반 예외 클래스는 주로 외부의 영향으로 발생할 수 있는 오류들로 보통 사용자에 의해서 발생하는 경우가 많습니다. 예를들어
실행 예외 클래스에는 주로 개발자의 실수에 의해서 발생될 수 있는 예외들로 자바 문법 요소와 관련된 오류들이 포함되어 있습니다. 예를 들어
앞서 예외는 개발자가 예측이 가능하기 때문에 발생한 예외에 대해 처리하는 코드 작성을 미리 해 줄 수 있다고 했습니다. 자바에서는 예외 처리를 위한 코드 작성을 위해 try-catch문을 제공합니다.
예외처리는 프로그램 실행 시 발생할 수 있는 예외에 대한 처리 코드를 미리 작성함으로써, 에러 발생 시 프로그램의 비정상적인 종료를 예방해주는 역할을 하며 다음과 같이 작성해 줄 수 있습니다.
try {
// 예외가 발생할 가능성이 있는 코드 작성
} catch(Exception1 e) {
// Exception1 유형의 예외 발생시 실행코드
} catch(Exception2 e) {
// Exception2 유형의 예외 발생시 실행 코드
} finally {
// 예외 발생 여부와 상관없이 항상 실행
// 필수 옵션은 아님
}
try의 블럭 안에는 예외가 발생할 가능성이 있는 코드를 입력합니다. 만약 예외 없이 정상적인 실행이 된다면 catch블럭은 실행하지 않고 바로 finally블럭 내의 코드가 실행됩니다.
만약 예외가 발생했지만 catch블럭에 일치하는 예외타입이 없다면 당연하게도 실행되지 않습니다.
앞서 소개해드린 try-catch문을 사용하는 것 외에도 예외 처리를 할 수 있는 방법이 있습니다. 바로 메서드에 throws 키워드를 사용하여 메서드 내에서 발생할 수 있는 예외 클래스를 작성해 주면 됩니다.
public void Example() throws Exception1, Exception2 {}
만약 throws키워드 뒤에 Exception을 작성하면 Exception은 모든 예외의 최상위 클래스이기 때문에 모든 종류의 예외가 발생가능하다는 것을 의미합니다.