1. 예외처리란(Exception, Error Handling)?
- 다양한 예외 상황에 대응하기 위해서 예외 처리 코드가 필요합니다.
- 예외처리의 목적
- 예외의 발생으로 인한 실행 중인 프로그램의 비정상 종료를 막기 위해서
- 개발자에게 알려서 코드를 보완할 수 있도록 하게 위해서
자바에서는 상속을 이용해서 모든 예외를 표현합니다. 모든 예외 클래스는 Throwable의 자손 클래스 입니다.
- Throwable 에는 크게 두 종류의 자식 클래스가 있습니다.
- Error 는 프로그램이 종료되어야 하는 심각한 문제를 표현합니다. 대부분 컴퓨터나 JVM이 시스템적으로 동작할 수 없는 상황을 표현합니다.</aside>
- <aside> 💡 Java는 JVM내의 Heap이라는 메모리 공간을 운영체제로부터 할당 받아 사용합니다. 할당 받을 수 있는 최대 메모리 이상을 사용하면, JVM이 다운될 수 밖에 없습니다. 이 경우 OutOfMemoryError가 나면서 프로그램이 종료됩니다. 자바의 대표적인 에러 상황으로 줄여서 OOM이라고도 합니다.
- Exception 은 프로그램이 종료되지는 않지만 예외나 문제상황을 표현하기 위해 사용합니다.
- 자바에 미리 정의 되어있는 예외 클래스 들이 있습니다. 기본적으로 이미 있는 것을 사용하시되, 필요한 것으로 표현할 수 없거나 구체적인 목적을 가진 예외를 정의하고 싶다면, Throwable 또는 그 하위에 있는 예외 클래스를 상속받아서 자신만의 예외 클래스를 정의할 수 있습니다. (아래 사진은 자바의 기본 예외 클래스들 중 대표적인 것들의 상속 관계도 입니다.)
- 실행도중 발생하는 Exception은 RuntimeException을 상속받아서 정의하세요.
- 파일을 읽고 쓰거나, 원격에 있는 저장소로부터 데이터를 읽고 쓸 때 나는 에러를 표현하려면 IOException을 상속받아서 정의하세요.
- try - catch 형식
try {
// 예외가 발생할 가능성이 있는 코드를 구현합니다.
} catch (FileNotFoundException e) {
// FileNotFoundException이 발생했을 경우,이를 처리하기 위한 코드를 구현합니다.
} catch (IOException e) {
// FileNotFoundException이 아닌 IOException이 발생했을 경우,이를 처리하기 위한 코드를 구현합니다.
} finally {
// 예외의 발생여부에 관계없이 항상 수행되어야하는 코드를 구현합니다.
}
# finally 구문은 필수가 아님
팁 tip
예외는 중복 catch 블럭을 사용하여 다양한 예외처리를 수행할 수 있습니다.
중복 catch블럭을 사용할 때는 먼저 선언된 catch블럭부터 확인합니다.
앞의 catch블럭에서 잡혔다면, 뒤의 catch블럭으로는 전파되지 않습니다.
좁은 범위의 예외부터 앞에 선언하는 것이 좋습니다.
여기서 좁은 범위란 상속관계에서 자식 클래스에 위치 할수록 좁은 범위입니다.
예를 들어서 IOException이 발생할 것 같아 예외처리를 하고,
그 외의 예외도 예외처리를 하고 싶다면 IOException을 catch 하는 구문을 먼저,
Exception 을 catch하는 구문을 그 뒤에 작성합니다.
- try-with-resource 형식
- try-catch문이외에 try-with-resource문도 존재합니다.
- 입출력과 함께 자주 쓰이는 구문입니다! 일반적으로 사용되었던 자원을 끝난 후에 닫아줘야 하는 것들이 존재하는데 여기서 try-catch-finally구문보다 편리한 것이 지금부터 설명드릴 try-with-resource 문입니다! (입출력에 대해서는 추후 배울 것이므로 지금은, *"입력과 출력에 대한 것이구나"*라고 생각하시면 됩니다.)
- 기존의 try-catch(-finally)문은 자원을 닫을 때 close()를 사용해야 합니다.
- try-with-resource문은 try문을 벗어나는 순간 자동적으로 close()가 호출됩니다.
- 어떻게 사용하면 될까요? → try()안의 입출력 스트림을 생성하는 로직을 작성할 때 해당 객체가 AutoClosable 인터페이스를 구현한 객체여야 합니다.
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try (FileOutputStream out = new FileOutputStream("test.txt")) {
// test.txt file 에 Hello Sparta 를 출력
out.write("Hello Sparta".getBytes());
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
이처럼 형식은 try-catch문과 비슷하지만, try()안에 AutoClosable 인터페이스를 구현한 객체를 선언하면 사용할 수 있습니다! 간단하지만, 매우 유용한 예외형식이죠!
👉 AutoClosable 인터페이스
AutoClosable 인터페이스에는 예외가 발생할 경우 close()메소드를 호출하기로 정의되어있습니다.
예외처리 예시
class ArrayCalculation {
int[] arr = { 0, 1, 2, 3, 4 };
public int divide(int denominatorIndex, int numeratorIndex)
throws ArithmeticException, ArrayIndexOutOfBoundsException {
return arr[denominatorIndex] / arr[numeratorIndex];
}
}
public class Main {
public static void main(String[] args) {
ArrayCalculation arrayCalculation = new ArrayCalculation();
System.out.println("2 / 1 = " + arrayCalculation.divide(2, 1));
try {
System.out.println(
"1 / 0 = " + arrayCalculation.divide(1, 0));
} catch (ArithmeticException arithmeticException) {
System.out.println("잘못된 계산입니다. " + arithmeticException.getMessage());
}
try {
System.out.println("Try to divide using out of index element = "
+ arrayCalculation.divide(5, 0));
} catch (ArrayIndexOutOfBoundsException arrayIndexOutOfBoundsException) {
System.out.println(
"잘못된 index 범위로 나누었습니다. 타당 index 범위는 0부터" + (arrayCalculation.arr.length - 1) + "까지 입니다.");
}
}
}
'프로그래밍 > Java' 카테고리의 다른 글
Collection(1) (List, Set, Map) (0) | 2022.05.18 |
---|---|
날짜, 시간 (0) | 2022.05.18 |
객체지향언어 (4) 추상클레스, 인터페이스 (0) | 2022.05.18 |
객체지향언어 (3) 접근제어자 (0) | 2022.05.17 |
객체지향언어 (2) 상속, overloading, overriding (0) | 2022.05.17 |