훈수/저작권 관련 지적 환영합니다 - 댓글 또는 audgnssweet@naver.com
종류
자바에서 오류는
컴파일 시에 발생하는 컴파일 에러 (프로그램이 실행되지 않음)
실행 도중에 문제가 생겼을 때 발생하는 런타임 에러(프로그램이 종료됨)
이 있습니다.
원래 에러가 발생하면 프로세스가 종료됩니다.
그러나 프로그램이 반드시 종료되어야만 하는 경우가 아닐 때 (심각한 에러가 아닐 때)는
프로그래머가 직접 이런 오류를 handling 하여 원하는 처리를 할 수 있습니다.
런타임 에러 중 프로그래머가 컨트롤할 수 있는 것들을 예외라고 하고,
그렇지 않은 것들을 런타임 에러라고 합니다.
대표적인 런타임 에러로는 OutOfMemoryError가 있습니다. (메모리가 부족하면 어떤 방법으로든 해결이 안 되기 때문에 프로그램을 종료해야겠죠?)
대표적인 예외로는 ArithmeticException이 있습니다. (0으로 나누기를 하려고 할 때)
이런 예외는 프로그래머가 다시 입력을 받는다던지 하는 방식으로 처리가 가능하겠죠?
물론 이런 예외들도 런타임 에러기 때문에, 프로그래머가 따로 처리를 하지 않는다면 프로세스가 종료됩니다.
try - catch (finally)
자바에서는 에러 처리를 할 때, try - catch 블록을 사용합니다.
try에는 에러가 발생할 가능성이 있는 코드들이 들어가고,
catch() 에는 발생 가능한 에러를 명시함으로써 에러 발생 후 뒤처리를 합니다.
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n1, n2, result;
n1 = scanner.nextInt();
n2 = scanner.nextInt();
try {
System.out.printf("%d / %d = %d", n1, n2, n1 / n2); <- 에러 발생 가능 코드
} catch (ArithmeticException e) { <- 처리할 에러 명시
System.out.println("0으로 나눌 수 없습니다");
} catch (Exception e) {
System.out.println("에러 발생");
}
}
위와 같이 catch를 여러 개 중첩시킴으로써 여러 개의 에러를 핸들링할 수 있습니다.
try {
System.out.printf("%d / %d = %d\n", n1, n2, n1 / n2);
return 0;
} catch (ArithmeticException e) {
System.out.println("0으로 나눌 수 없습니다");
} finally {
System.out.println("프로그램 종료");
}
여기서 finally는, 위의 try catch에서 에러가 발생하든 발생하지 않든 무조건 실행되는 코드입니다.
위의 try에서 return으로 프로그램을 종료한다고 해도, 종료되기 전에 finally 블록을 실행하고 종료합니다.
try-catch vs if-else
try-catch로 발생하는 에러를 '후처리' 한다면,
if-else로는 발생할 수 있는 에러에 대해서 선처리로 발생을 방지할 수 있습니다.
if (n2 == 0) {
System.out.println("0으로 나눌 수 없습니다");
}else {
System.out.printf("%d / %d = %d\n", n1, n2, n1 / n2);
}
위와 같이 말이죠.
하지만 발생할 수 있는 에러의 종류가 많아지거나, 조건이 너무 많아지게 된다면 오히려 코드의 가독성을 해칠 수 있습니다.
만약 나눗셈 위에 else-if문이 5개 이상 붙어있다면 어떻게 될까요?
읽는 사람 입장에서 그 코드의 본 목적을 파악하기가 힘들 것입니다.
반면 try-catch에서 catch가 여러 개일지라도, 코드의 본 목적(핵심 로직) 은 맨 위 try 블록 안에 들어있기 때문에 그 코드의 목적을 명확하게 파악하기가 좀 더 쉽습니다.
에러 객체
자바에는 primitive type과 reference type이 있다는 것을 아실 것입니다.
그리고 대부분의 자료형은 reference type(객체)입니다.
이런 Exception도 마찬가지로 "객체" - 클래스입니다.
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n1, n2, result;
n1 = scanner.nextInt();
n2 = scanner.nextInt();
try {
System.out.printf("%d / %d = %d", n1, n2, n1 / n2); <- 에러 발생 가능 코드
} catch (ArithmeticException e) { <- 처리할 에러 명시
System.out.println("0으로 나눌 수 없습니다");
} catch (Exception e) {
System.out.println("에러 발생");
}
}
위의 클래스에서 ArithmeticException e 객체는 어떻게 생기는 것일까요?
맞습니다. JVM에서 에러가 발생하면, 해당 에러에 대한 여러 정보들을 객체로 매핑시켜 e라는 변수 안에 넣어주는 것입니다.
} catch (ArithmeticException e) {
System.out.println("0으로 나눌 수 없습니다");
e.getMessage();
e.getCause();
e.getStackTrace();
}
그래서 위와 같이 e 객체를 사용하면 우리가 직접 넣어주지 않았음에도 불구하고 여러 가지 정보를 얻을 수 있습니다.
자바의 에러 처리에 대해서 알아보았는데요,
에러 처리를 잘 한 프로그램일수록 안전성이 높아지므로
에러 처리에 대한 공부, 노력이 필요하겠습니다.
'Java' 카테고리의 다른 글
생성자 (0) | 2021.04.13 |
---|---|
클래스와 객체(미완성) (0) | 2021.04.06 |
자바 배열과 메모리 (0) | 2021.03.30 |
레퍼런스 변수와 메모리, 에러 (0) | 2021.03.30 |
Scanner로 키보드 입력 받기 (0) | 2021.03.23 |