🔍 오류와 예외의 차이
✍ 오류 (Error)
- 프로그램 자체 또는 JVM 등의 치명적인 원인으로 발생하는 문제점이다.
- 오류가 발생하면 프로그램은 강제로 종료된다
- 개발자가 수정이 불가능한 문제!
✍ 예외 (Exception)
- 사용자의 잘못된 조작 실수 또는 개발자의 잘못된 코딩등으로 인해 발생하는 문제점이다.
- 예외가 발생하면 프로그램은 강제로 종료된다.
- 오류와 달리 개발자는 예외 상황이 발생했을 때의 대처 방안을 기술할 수 있다.
✍ 예외 관련 용어
1. 예외가 발생했을 때 예외 발생 여부를 감지하는 대상 : 리스너(Listener)
2. 예외가 발생했을 때 정상적으로 종료될 수 있도록 처리하는 것 : 예외처리
=> 예외가 발생하지 않도록 미리 원인을 제거하는 것은 예외 처리가 아니다.
예외가 발생할 상황을 미리 탐지하여 예외가 발생했을 때
프로그램이 정상 종료되도록 처리하는 것을 예외 처리라고 한다.
✍ 예외 발생 예시
public static void main(String[] args) {
int a = 10;
int b = 0;
System.out.println("a / b = " + (a/b));
}
=> 자바에서는 나누는 수가 0일 경우 예외가 발생한다!
💻
=> 예외 발생 문구
여기서
- Exception in thread "main" java.lang.ArithmeticException => 예외 발생 상황 정보 및 예외 발생을 탐지한 예외 클래스명
- by Zero => 예외 발생 원인 메세지
- at test.tet11.main(test11.java:8) => 예외 발생 위치
public static void main(String[] args) {
String str = null;
System.out.println(str.length());
}
💻
=> 참조변수 str에 저장된 값이 없다. 그래서 str.length()에 접근하여 문자열의 길이를 구하지 못하기 때문에 예외가 발생
✍ 가장 대표적인 예외 발생 예시 : 배열
public static void main(String[] args) {
int[] arr = new int[5];
arr[6] = 5;
System.out.println(arr[6]);
}
💻
=> 배열 arr의 길이는 6이며 인덱스는 0~5까지이다. 그런데 배열에 존재하지 않는 인덱스 6번에 접근하려고 하니
예외가 발생한다. 자바에서 흔히 볼 수 있는 예외상황이다.
🔍 예외의 종류
- 예외란 개발자가 의도하지 않은 상황에서 발생하는 문제
- 예외 발생 시 프로그램은 해당 지점에서 비정상적으로 종료된다
- 오류와 달리 심각도가 낮으며, 예외 처리를 통해 예외 발생 시 해결책을 기술하여
프로그램이 정상적으로 종료되도록 처리 가능하다.
- 예외 처리를 위해 try ~ catch 문을 사용하여 처리 작업 수행이 가능하다.
=> try 블록 내에서 예외 발생 가능성이 있는 코드들을 관리하고
예외가 발생했을 경우 JVM이 보내는 예외 객체를 전달 받아
catch 블록 중 해당 객체 타입과 일치하는 catch 블록을 실행하여 예외를 처리한다.
✍ Compile Checked Exception 계열 예외
- 컴파일 시점에서 예외 발생 가능성을 판별하므로, 예외 처리가 되어 있지 않으면 컴파일 에러가 발생한다
=> 즉, 예외 처리 강제성이 있다.
- 대표적인 예 : IOException, SQLException, ClassNotFoundException
✍ Compile Unchecked Exception 계열 예외
- 컴파일 시점에서 예외 발생 가능성을 판별할 수 없다.
실행 시점에서 예외 발생 여부가 판별되므로, 예외 처리 여부를 별도로 감시하지 않는다
=> 즉, 예외 처리 강제성이 없다. 그러므로 예외 발생이 예상되는 코드를 찾아 예외 처리를 수행해야 한다.
- 대표적인 예: RuntimeException 계열
(ArithmeticException, ArrayIndexOutOfBoundsException, NullPointerException, ClassCastException 등)
=> java.lang 패키지 내에 Exception 클래스와 서브 클래스등이 제공되며
각 예외는 자신의 슈퍼클래스 타입으로 업캐스팅도 가능하다.
✍ try ~ catch 블록 예외 처리 예시 - ArithmeticException 예외
public static void main(String[] args) {
System.out.println("프로그램 시작!");
try { // try 블록 내부에 예외 발생 가능성 코드 작성
System.out.println("try 블록 시작!");
int a = 10;
int b = 0;
System.out.println("a / b = " + (a/b));
System.out.println("try 블록 끝!");
} catch (ArithmeticException e) { // 예외 처리
System.out.println("ArithmeticException 예외 발생!");
}
System.out.println("프로그램 종료!");
}
💻 예외가 발생했을 경우
=> 나누는 수가 0일 경우 나눗셈 연산에서 예외가 발생한다. try 블록 내에서 예외 처리 후
프로그램이 정상적으로 종료된 것을 확인할 수 있다.
💻 예외가 발생하지 않았을 경우
public static void main(String[] args) {
System.out.println("프로그램 시작!");
try { // try 블록 내부에 예외 발생 가능성 코드 작성
System.out.println("try 블록 시작!");
int a = 10;
int b = 2;
System.out.println("a / b = " + (a/b));
System.out.println("try 블록 끝!");
} catch (ArithmeticException e) { // 예외 처리
System.out.println("ArithmeticException 예외 발생!");
}
System.out.println("프로그램 종료!");
}
=> try 블록 내부의 코드에서 예외가 발생하지 않았기 때문에 나눗셈 연산이 정상적으로 실행되었다.
try 블록 종료 문자열이 출력된 후, 프로그램도 정상적으로 종료된 것을 확인할 수 있다.
✍ try ~ catch 블록 예외 처리 예시 - ArrayIndexOutOfBoundsException
public static void main(String[] args) {
System.out.println("프로그램 시작!");
try {
System.out.println("try 블록 시작!");
int[] arr = {0, 1, 2};
System.out.println(arr[3]);
System.out.println("try 블록 끝!");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("ArrayIndexOutOfBoundsException 예외 발생!");
}
System.out.println("프로그램 종료!");
}
💻 예외가 발생 했을 경우
=> 예외가 발생하여 catch문 안의 예외 발생 문자열이 출력된 후 프로그램이 종료되었다.
💻 예외가 발생하지 않았을 경우
public static void main(String[] args) {
System.out.println("프로그램 시작!");
try {
System.out.println("try 블록 시작!");
int[] arr = {0, 1, 2};
System.out.println(arr[2]);
System.out.println("try 블록 끝!");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("ArrayIndexOutOfBoundsException 예외 발생!");
}
System.out.println("프로그램 종료!");
}
=> try 블록 내부의 인덱스 출력문이 정상적으로 작동된 후 프로그램이 종료된 걸 확인할 수 있다.
🔍 하나의 try 블록에서 여러개의 예외를 처리하는 경우
- try 블록 내에서 처리해야 하는 예외가 2 종류 이상일 경우
catch 블록을 해당 예외 종류만큼 작성하거나
하나의 catch 블록에서 복수개의 예외를 모두 처리하는 클래스를 사용하면 된다.
- 복수개의 catch 블록은 첫번째 catch 블록부터 차례대로 탐색한다.
=> 만약, 끝까지 탐색했음에도 일치하는 catch 블록이 없으면 실행 시 예외가 발생한다.
- 만약 복수개의 catch 블록 지정 시 하위 타입부터 상위 타입순으로 나열해야 한다.
즉, ArithmeticException 보다 Exception 클래스가 위에 있을 수 없다는 말이다.
- 만약, 하나의 catch 블록으로 복수개의 예외를 처리하려면
1) catch 블록의 클래스를 복수개의 예외 클래스의 상위 타입으로 지정하거나
(모든 예외를 처리하기 위해서는 Exception 클래스를 지정)
2) catch 블록 클래스에 | => 버티컬바 기호를 사용하여 복수개의 클래스를 기술해도 된다.
(ex. FileNotFoundException | ClassNotFoundException)
✍ 여러개 예외 처리 예시
public static void main(String[] args) {
System.out.println("프로그램 시작!");
try {
System.out.println("try 블록 시작!");
// 첫번째 예외
int a = 10, b = 0;
System.out.println("a / b = " + (a/b));
// 두번째 예외
String str = null;
System.out.println(str.length());
// 세번째 예외
int[] arr = {0, 1, 2};
System.out.println(arr[3]);
System.out.println("try 블록 끝!");
} catch (ArithmeticException e) {
System.out.println("예외 발생! 0으로 나눌 수 없습니다.");
} catch (NullPointerException e) {
System.out.println("예외 발생! null값을 참조할 수 없습니다.");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("예외 발생! 잘못된 인덱스를 참조합니다.");
} catch (Exception e) {
System.out.println("예외 발생 : 나머지 예외를 모두 처리");
}
System.out.println("프로그램 종료!");
}
=> 만약 여기서 첫번째 예외가 발생한다면?
💻
=> 예외 발생시 프로그램은 즉시 종료되므로, 두번째 세번째 코드는 실행되지 않는다.
'개발 > Java' 카테고리의 다른 글
[Java] 예외 처리 위임(던지기 => throws) (0) | 2023.03.01 |
---|---|
[Java] try ~ catch ~ finally (0) | 2023.03.01 |
[Java] Wrapper 클래스 (0) | 2023.02.25 |
[Java] toString() 메서드 (0) | 2023.02.25 |
[Java] Enum 설계하기 (0) | 2023.02.22 |