예외가 생길 것을 미리 예측해서 대비하는 것으로 비정상적인 종료를 막는 등 굉장히 중요한 부분이다.
자바에서는 상속을 이용해서 모든 예외를 표현한다.
모든 예외 클래스는 Throwable의 자손 클래스 이다.
Throwable 에는 크게 두 종류의 자식 클래스가 있다.
Java는 JVM내의 Heap이라는 메모리 공간을 운영체제로부터 할당 받아 사용한다.
할당 받을 수 있는 최대 메모리 이상을 사용하면, JVM이 다운될 수 밖에 없다. 이 경우 OutOfMemoryError가 나면서 프로그램이 종료된다.
Exception은 크게 두 가지(RuntimeException, IOException) 로 나누어 지는데
코드로 보면 이해가 쉬울 것이다.
try {
// 예외가 발생할 가능성이 있는 코드를 구현
} catch (FileNotFoundException e) {
// FileNotFoundException이 발생했을 경우,이를 처리하기 위한 코드를 구현
} catch (IOException e) {
// FileNotFoundException이 아닌 IOException이 발생했을 경우,이를 처리하기 위한 코드를 구현
} finally {
// 예외의 발생여부에 관계없이 항상 수행되어야하는 코드를 구현
}
보시는 거와 같이 finally는 필수는 아니지만 만약 작성을하면 계속 실행되는 코드이다.
tip!
예외는 중복 catch 블럭을 사용하여 다양한 예외처리를 수행할 수 있다.
중복 catch블럭을 사용할 때는 먼저 선언된 catch블럭부터 확인한다.
앞의 catch블럭에서 잡혔다면, 뒤의 catch블럭은 들어가지 않는다.
좁은 범위의 예외부터 앞에 선언하는 것이 좋다.
예를 들어서 IOException이 발생할 것 같아 예외처리를 하고, 그 외의 예외도 예외처리를 하고 싶다면 IOException을 catch 하는 구문을 먼저, Exception 을 catch하는 구문을 그 뒤에 작성합니다.
public class Main {
public static void main(String[] args) {
int number = 10;
int result;
for (int i = 10; i >= 0; i--) {
try {
result = number / i;
System.out.println(result);
} catch (Exception e) {
System.out.println("Exception발생: " + e.getMessage());
} finally {
System.out.println("항상 실행되는 finally 구문");
}
}
}
}
catch (Exception e) {
System.out.println("Exception발생: " + e.getMessage());
위 catch문을 잘 이해하면 좋다!
try-catch 이외에 try-with-resource문도 존재한다.
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부분이 어색한데, 괄호안에 올 수 있는 것은 closeable 을 구현한 클래스만 올 수 있고, 원래대로 작성한다면
public static void main(String[] args) throws IOException {
FileOutputStream out = new FileOutputStream("test.txt");
try {
// test.txt file 에 Hello Sparta 를 출력
out.write("Hello Sparta".getBytes());
out.flush();
} catch (IOException e) {
System.out.println("IOException발생: " + e.getMessage());
e.printStackTrace();
}
out.close();
}
out.close() 즉 파일을 열었으니 닫아주는 코드도 넣어주고,
throws IOException로 exception이 발생할 수 있는 것을 알려주는 것도 넣어줘야 한다.
catch문을 이용해서 예외처리를 하지 않은 경우, 메소드에 throws로 예외가 발생할 수 있다는 것을 알려주어야 한다.
throws 키워드가 있는 함수를 호출한다면, caller 쪽에서 catch와 관련된 코드를 작성해주어야 한다.
void method() throws IndexOutOfBoundsException, IllegalArgumentException
{
//메소드의 내용
}
느낀점
나는 넓은 범위의 예외처리부터 하면 좋을 것이라 생각했지만 아니었다.
한층 더 성장한 거 같아서 기분이 좋다.