Exception Handling
예외 처리
- 예상치 못한 문제를 Error 또는 Exception이라 부르는데, 이 둘 사이에는 아래와 같은 차이가 있다:
- Error (에러)
- 컴퓨터 하드웨어의 고장으로 인해 응용프로그램 실행 오류가 발생하는 것을 의미한다. - Exception (예외)
- 잘못된 코드로 인해 발생한 오류를 의미한다.
- Error와 달리, Exception은 예외 처리를 통해 오류가 발생되어도 프로그램의 실행 상태를 계속 유지할 수 있다.
- 자바에서는 예외가 발생하면 Exception
Class 로 부터 Object 를 생성하는데,
프로그래머는 이를 활용하여 예외를 처리한다.
Hierarchy of Throwable
Class (Throwable
클래스 상속 구조)
- 자바의 모든 Error
Class 와 Exception
Class 는 Throwable
Class 를 상속받아 만들어진다.
- 특히, 실행 예외는 RuntimeException
Class 와 그의 Derived Class 들에서 처리한다.
- RuntimeException
이외의 다른 예외들은 모두 일반 예외로 분류된다.
Flow of Exception Handling (예외 처리 제어 흐름)
try
Block
- 예외가 발생될 가능성이 있는 코드들이 위치하는 블록이다.
catch
Block
- try
블록에서 해당 예외가 발생시 어떻게 대처할 것인지를 명시하는 블록이다.
- 예외가 발생했을때, catch
블록이 여러개라 할지라도 catch
중 하나만 실행된다.
(하나의 예외가 발생하면 즉시 실행을 멈추고 해당 catch
블록으로 이동하기 때문이다.)
- 예외가 발생되면 먼저 명시된 catch
블록부터 검사하기 시작하는데
처리해야 할 예외 클래스들이 상속 관계에 있을 경우,
하위 클래스 catch
블록을 먼저 명시하고,
상위 클래스 catch
블록을 나중에 명시해야 한다.
- 두 개 이상의 예외를 하나의 catch
블록에서 처리하고자 하는 경우, | 연산자로 연결한다.
finally
Block
- 예외 발생 여부와 관계없이, finally
블록은 항상 실행되며,
try
블록과 catch
블록에서 return
문을 사용하더라도 finally
블록은 항상 실행된다.
- finally
블록은 생략 가능하다.
Example. Exception Handling by try-catch
Blocks
public class ExceptionHandlingExample {
public static void main(String[] args) {
String[] array = {"100", "loo", null, "200"};
for(int i=0; i<=array.length; i++) {
try {
int value = Integer.parseInt(array[i]);
System.out.println("array[" + i + "]: " + value);
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("Out of index: " + e.getMessage());
{ catch(NullPointerException | NumberFormatException e) { // 두 가지 이상의 예외를 한 번에 처리
System.out.println("Wrong data: " + e.getMessage());
}
}
}
}
try-with-resources Block
- 예외 발생 여부와 관계없이, 리소스를 자동으로 닫게 하는 구문이다.
- try 블록을 명시할 때, 괄호에 리소스를 Open 하는 코드를 작성하면,
try 블록이 정상적으로 완료되거나 예외가 발생했을 때 자동으로 리소스를 닫아준다.
(다수의 리소스를 컨트롤하고자 하는 경우, 세미콜론(;)으로 구분지어 놓는다.)
- 이때, 해당 리소스를 닫는 java.lang.AutoCloseable Interface의 close() 메소드를 재정의(구현)해야한다.
- try 괄호 안에 리소스 변수를 반드시 선언해야 한다. (- Java 8)
- try 괄호 안에 리소스 변수를 선언하거나, 외부 리소스 변수를 사용할 수 있다. (Java 9 - Current)
* Resource (리소스)
- 데이터를 제공하는 객체를 의미한다.
- File 등이 리소스에 해당된다.
Example. try-with-resources Block
// Single Resource
try(FileInputStream fis = new FileInputStream("file.txt")){
...
} catch(IOException e) {
...
}
// Multiple Resources
try(
FileInputStream fis1 = new FileInputStream("file1.txt");
FileInputStream fis2 = new FileInputStream("file2.txt")
) {
...
} catch(IOException e) {
...
}
// External Resources (Java 9)
FileInputStream fis1 = new FileInputStream("file1.txt");
FileInputStream fis2 = new FileInputStream("file2.txt");
try(fis1; fis2) {
...
} catch(IOException e) {
...
}
// Overriding
public class FileInputStream implements AutoCloseable {
...
@Override
public void close() throws Exception {...}
}
Specifying the Exceptions Thrown by a Method (메서드 정의 시, 발생되는 예외 명시하기) (JDK 8)
- Method 에서 발생될 수 있는 예외를 선언부에 명시해줌으로써 JVM Call Stack 이 예외를 처리하도록 지정할 수 있다.
- 즉, 메소드 내부에서 발생한 예외를 메소드 내부에서 처리하는 것이 아닌,
메소드를 호출한 부분에서 처리하도록 하는 메커니즘이다.
- 나열해야 할 예외 클래스가 많은 경우, throws Exception
또는 throws Throwable
만으로 모든 예외를 떠넘길 수 있다.
- main()
메소드에서도 발생될 수 있는 예외를 명시할 수 있는데,
이럴 경우 main()
Method에서 발생되는 예외는 JVM이 처리하게 되며,
JVM은 예외 내용을 콘솔에 출력하는 것으로 예외를 처리한다.
Syntax. Specifying the Exceptions Thrown by a Method
<return-type> <method-name>(<parameters>) throws <exception-class1>[, <exception-class2>, ...] {
...
}
// Exameple
public void method2() throws ClassNotFoundException {
...
}
public void writeList() throws IOException, IndexOutOfBoundsException {
...
}
public static void main(String[] args) throws Exception {
...
}
Example. Specifying the Exceptions Thrown by a Method
public void method1() {
try {
method2();
} catch(ClassNotFoundException e) { // method2() 를 호출한 부분에서 예외를 처리
System.out.println("Exception: " + e.getMessage());
}
}
public void method2() throws ClassNotFoundException {
Class.forName("java.lang.String2"); // ClassNotFoundException 발생 가능성이 있는 부분
}
Reference: Oracle, Lesson: Exceptions, URL, 2023년 2월 5일 검색
Reference: 신용권, 임경균; 이것이 자바다(개정판); 한빛미디어; 2022