728x90
반응형
예외 Exception
- 오류Error 는 시스템의 치명적인 문제로 인해 발생하는 문제이며 개발자가 코드 상에서 해결이 불가능한 문제를 말하지만 예외Exception는 코드 상에서 실수 등으로 인해 발생하는 문제이며 개발자가 코드 상에서 해결이 가능한 문제
- 예외가 발생할 경우 발생 시점에서 프로그램은 비정상적으로 종료됨
- 예외가 발생했을 때 프로그램이 비정상적으로 종료되지 않도록 추가적인 작업을 수행하여 정상적으로 종료되도록 하는 것을 예외 처리Exception Handling 라고 한다.
- 예외가 발생되면 해당 예외에 대한 처리를 담당하는 클래스의 객체를 생성한 뒤 예외 메세지를 포함하여 예외를 던짐(throw) 따라서, 해당 객체를 전달받아 예외를 처리해야함 try ~ catch 문을 사용하여 기본적으로 예외 처리가 가능
- 예외가 발견되는 시점에 따라 Compile Checked Exception 계열과 Compile ex) RuntimeException 계열(ArithmeticException 등) 계열로 나뉨
- Compile Checked Exception : 컴파일 시점(코드 작성 시점)에서 예외 처리 여부를 판단하여 예외가 처리되지 않으면 예외 발생 알림 ex) IOException, SQLException, FileNotFoundException 등
- Compile Unchecked Exception : 컴파일 시점에서는 예외 처리 여부를 검사하지 않고, 실행 시점에서 예외가 발생하면 예외 발생 알림 ex) RuntimeException 계열(ArithmeticException 등)
RuntimeException 계열(Compile Unchecked Exception 계열)
- ArithmeticException
- 수치 데이터를 0으로 나눌 때 발생하는 예외 등
- ArrayIndexOutOfBoundsException
- 배열 인덱스가 잘못 되었을 경우 발생
- NullPointerException
- 참조 변수에 null 값이 저장된 상태에서 참조할 경우 발생 null 이 저장된 참조 변수의 .XXX() 형태로 메서드 호출 시
- ClassCastException
- 객체의 강제 형변환 시 잘못 되었을 경우 발생
public class Ex4 {
public static void main(String[] args) {
System.out.println("프로그램 시작!");
int num = 3;
// System.out.println(num / 0); // ArithmeticException 예외 발생
// 예외 발생 시점부터 나머지 모든 코드의 실행이 불가능하며
// 프로그램이 비정상적으로 종료됨
int[] arr = new int[3];
// arr[3] = 10; // ArrayIndexOutOfBoundsException 예외 발생
String str = null;
// System.out.println(str.length()); // NullPointerException 예외 발생
Animal ani = new Dog();
Cat cat = (Cat)ani; // ClassCastException 예외 발생
System.out.println("프로그램 종료!");
}
}
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
예외 처리 Exception Handling
- 예외가 발생할 경우 예외가 발생하지 않도록 예외 발생 코드를 수정하는 것이 아니라 예외가 발생하더라도 별도의 작업을 통해 작업이 끝까지 수행되어 프로그램이 정상적으로 종료될 수 있도록 처리하는 것
- try~catch 블록을 사용하여 기본적인 예외 처리 try 블록 내에 예외가 발생할 것으로 예상되는 코드를 기술하고 catch 블록에서 예외를 전달받을 클래스를 선언하여 예외 감지 후 해당 예외를 처리할 코드를 기술
기본 문법
try {
// 예외 발생 예상 코드들...
} catch(예외클래스명 변수명) {
// 해당 예외 발생 시 수행할 코드들...
}
System.out.println("프로그램 시작!");
int num = 3, num2 = 0;
// 0으로 나눗셈 수행 시 예외가 발생하는데
// 0으로 나누지 않도록 데이터를 수정하는 것 등은 예외처리가 아님
try {
System.out.println(num / num2); // 예외 발생 예상 코드
// try 문 내에서 예외 발생 지점부터 아래쪽의 모든 문장들은
// 실행되지 못하고 바로 catch 블록으로 이동함
System.out.println("try 문 종료"); // 예외 발생 시 실행되지 못함
} catch(ArithmeticException e) {
// ArithmeticException 예외 발생 시에 자동으로 실행되는 부분
// => ArithmeticException 예외가 발생하지 않으면 실행되지 못함
System.out.println("0으로 나눌 수 없습니다!");
}
// 예외 발생 여부와 관계없이 실행되는 코드들...
System.out.println("프로그램 종료!");
두 가지 이상의 예외가 발생할 가능성이 있는 경우
두 가지 이상의 예외를 각각의 catch 블록에서 처리
- 두 개 이상의 catch 블럭을 작성하여 각 예외를 별도로 처리 단, 예외 발생 시 윗쪽 catch 블럭부터 아래쪽으로 순서대로 탐색
System.out.println("프로그램 시작!");
try {
num2 = 0;
// System.out.println(num / num2); // 예외 발생 예상 코드
String str = null;
System.out.println(str.length()); // 예외 발생 예상 코드
} catch (ArithmeticException e) {
System.out.println("ArithmeticException 만 처리!");
} catch (NullPointerException e) {
System.out.println("NullPointerException 만 처리!");
}
System.out.println("프로그램 종료!");
두 가지 이상의 예외를 하나의 catch 블록에서 처리
1. 하나의 catch 블록에 2개 이상의 예외클래스를 모두 지정할 경우
OR 기호 | 를 사용하여 예외 클래스끼리 묶어줌
System.out.println("프로그램 시작!");
try {
num2 = 0;
System.out.println(num / num2); // 예외 발생 예상 코드
String str = null;
System.out.println(str.length()); // 예외 발생 예상 코드
} catch (ArithmeticException | NullPointerException e) {
System.out.println("ArithmeticException 과 NullPointerException 만 처리!");
}
System.out.println("프로그램 종료!");
2. 하나의 catch 블록에 상위 예외클래스를 사용하여 처리
System.out.println("프로그램 시작!");
try {
num2 = 0;
// System.out.println(num / num2); // 예외 발생 예상 코드
String str = null;
System.out.println(str.length()); // 예외 발생 예상 코드
// } catch (RuntimeException e) {
// System.out.println("RuntimeException 계열만 처리!");
} catch (Exception e) {
System.out.println("모든 예외 처리!");
// } catch (RuntimeException e) {
// System.out.println("RuntimeException 계열만 처리!");
}
// => 주의!! 여러개의 예외 클래스를 사용할 경우
// 예외클래스간의 상속관계에서 하위클래스 타입부터
// 역순으로 처리해야된다!
System.out.println("프로그램 종료!");
반응형
try ~ catch ~ finally 블록
- try 블록에서 예외 발생 여부와 관계 없이 무조건 실행해야하는 문장들은 finally 블록 내에 기술함
- 예외가 발생하거나 발생하지 않아도 무조건 실행되며 심지어 return 문을 만나 메서드 실행이 종료될 때도 finally 블록 내의 코드를 실행한 후 종료
- 주로, 자원 반환을 위한 코드를 기술 ex. DB 접속 종료, 입출력 스트림 종료 등
기본 문법
try {
// 예외 발생 예상 코드들...
} catch(예외클래스명 변수명) {
// 해당 예외 발생 시 수행할 코드들...
} finally {
// 예외 발생 여부와 관계없이 수행할 코드들..
}
public static void exceptionMethod(int num) {
/*
* 예외가 발생할 경우 실행되는 코드 순서
* 1 -> 3 -> 4(finally) -> 5 -> 메서드 종료
* (return 문을 만나지 않으므로 try 블록 바깥 코드도 실행됨)
*
* 예외가 발생하지 않을 경우 실행되는 코드 순서
* 1 -> 2 -> return -> 4(finally) -> 메서드 종료
* (return 문을 만나더라도 finally 블록을 우선 실행함)
*/
try {
System.out.println("Code1 : num = " + num);
int total = 1 / num; // 예외 발생 예상 코드
System.out.println("Code2 : 예외 발생 없음!");
return; // 메서드 실행 도중 return 문을 만나면
// 메서드를 호출한 곳으로 즉시 되돌아가지만
// finally 블록 내의 코드가 있을 경우 해당 코드를 실행한 후
// 메서드를 호출한 곳으로 돌아감
} catch (Exception e) {
System.out.println("Code3 : 예외 발생 후 처리 완료!");
} finally {
System.out.println("Code4 : 예외 발생 여부와 관계없이 항상 실행!");
}
System.out.println("Code5 : try 문 종료 후 실행!");
}
System.out.println("프로그램 시작!");
int num1 = 10, num2 = 0;
String str = null;
try {
// ArrayIndexOutOfBoundsException 발생 가능성이 있는 코드
// System.out.println(num1 / num2);
// NullPointerException 발생 가능성이 있는 코드
// System.out.println(str.length());
System.out.println("예외 없음!");
} catch (Exception e) {
System.out.println("모든 예외 처리!");
} finally {
System.out.println("예외 발생 여부와 관계없이 무조건 실행!");
}
System.out.println("프로그램 종료!");
System.out.println("===========================");
System.out.println("메서드 호출 시작!");
exceptionMethod(0);
System.out.println("메서드 호출 종료!");
예외 처리에 대한 위임(throws 키워드)
- 예외 처리를 예외가 발생한 곳에서 직접 처리하지 않고 메서드를 호출한 곳으로 발생한 예외를 떠넘길 때 사용
- 메서드 정의 시 마지막에 throws 키워드를 명시하고 예외가 발생할 것으로 예상하는 클래스명을 지정하면 해당 예외 발생 시 try ~ catch 블록이 없을 경우 메서드를 호출한 곳으로 예외를 던진다. 이 때, 위임받은 곳에서 해당 예외를 처리(try ~ catch)해야함
- 메서드를 호출하는 외부에서 메서드 호출 시점에 예외 발생 여부를 판별하고, 예외를 처리할 수 있도록 해주며 또한, 메서드를 호출하는 Caller 에서 여러 메서드 내의 예외를 한꺼번에 묶어서 처리할 수 있도록 해준다!
public static void 과장() throws Exception { // 모든 예외를 위임
// 2개의 예외를 위임받아 과장이 직접 처리할 경우
// => 각각의 예외를 따로 catch 하거나 | 기호로 다중 catch 묶을 수 있음
// try {
// 대리();
// } catch (ClassNotFoundException | SQLException e) {
// System.out.println("과장이 ClassNotFoundException & SQLException 예외를 직접 처리!");
// }
// 2개의 예외를 위임받아 과장이 직접 처리하지 않고 위임할 경우
// => 각 예외 클래스 모두를 throws 뒤에 명시하거나
// 예외 클래스를 통합하여 상위 클래스명을 명시할 수도 있다!
대리();
}
public static void 대리() throws SQLException, ClassNotFoundException {
// 예외를 위임받아 대리가 직접 처리할 경우
// try {
// 사원();
// 사원2();
// } catch (ClassNotFoundException e) {
// System.out.println("대리가 ClassNotFoundException 예외를 위임받아 처리!");
// } catch (SQLException e) {
// System.out.println("대리가 SQLException 예외를 위임받아 처리!");
// }
// 대리가 위임받아 직접 처리하지 않고 과장()에게 위임할 경우
사원(); // SQLException
사원2(); // ClassNotFoundException
}
public static void 사원() throws SQLException {
// 예외 발생 시 예외가 발생한 곳에서 직접 예외를 처리하는 방법
// try {
// Connection con = DriverManager.getConnection(""); // SQLException
// } catch (SQLException e) {
// System.out.println("사원이 SQLException 예외를 직접 처리!");
// }
// 예외 발생 시 예외가 발생한 곳에서 처리하지 않고
// 예외가 발생한 메서드를 호출한 곳으로 예외를 떠넘기는 방법
// => 발생할 것으로 예상되는 예외클래스명을
// 메서드 선언부 마지막에 throws 키워드 뒤에 명시
Connection con = DriverManager.getConnection(""); // SQLException
// => throws SQLException 명시할 경우
// 현재 사원() 메서드를 호출한 대리() 메서드 내의
// 사원() 메서드 호출 코드에 예외 처리가 위임됨
}
public static void 사원2() throws ClassNotFoundException {
// ClassNotFoundException 예외를 대리에게 위임
Class.forName("");
}
try {
과장();
} catch (Exception e) {
System.out.println("main() 메서드(사장)가 모든 예외 위임받아 처리!");
}
throw 키워드
- 개발자가 직접 예외를 발생시킬 때 사용
- 자바 문법에서 위반되지 않는 코드라도 강제로 예외 발생 가능
- 예외를 발생시킬 위치에 throw 키워드 뒤에 발생시킬 예외 클래스의 객체를 생성하여 강제로 예외를 발생시켜 던짐
class InvalidScoreException extends Exception {
// 1. 생성자를 정의하여 예외 메세지를 전달받을 수 있는
// String 타입 파라미터 1개를 갖는 생성자 오버라이딩
public InvalidScoreException(String message) {
// 전달받은 메세지를 Exception 클래스의 생성자에서 초기화 수행
super(message);
}
}
public static void score(int score) throws Exception {
// int형 파라미터에 정수 150 이 전달될 경우 문법적으로는 맞지만
// 점수 범위(0 ~ 100) 기준으로 논리적으로 맞지 않은 값이 전달됨
// 따라서, 이 때 개발자가 직접 강제로 예외를 발생시킬 수 있다.
if(score >= 0 && score <= 100) {
System.out.println("학점 계산!");
} else {
// System.out.println(score + " : 점수 입력 오류!");
// try {
// // 강제로 예외를 발생시키기 위해 throw 키워드 사용
// // => throw 키워드 뒤에 예외 발생 클래스 객체 생성
// // 이 때, 파라미터로 예외 메세지 문자열을 전달 가능
// throw new Exception(score + " : 점수 입력 예외 발생!");
// // => try~catch 를 통해 예외 처리 또는 throws 를 통해 예외 위임
// } catch (Exception e) {
// // 예외 처리 시 전달받은 객체의 메서드를 통해 예외 정보 확인
// // 1. e.getMessage() : 예외 객체의 메세지 정보를 문자열로 리턴
//// System.out.println(e.getMessage());
//
// // 2. e.printStackTrace() : 예외 클래스명, 메세지, 발생 위치 등
// // 예외에 대한 상세 정보를 출력
// e.printStackTrace();
// }
// 외부로 예외를 떠넘길 경우
throw new Exception(score + " : 점수 입력 예외 발생!");
}
}
public static void score2(int score) throws InvalidScoreException {
// 사용자 정의 예외 클래스를 사용하여 강제로 예외 발생시키기
if(score < 0 || score > 100) {
throw new InvalidScoreException(score + " : 점수 입력 예외 발생!");
}
}
try {
score(150);
} catch (Exception e) {
e.printStackTrace();
}
try {
score2(150);
} catch (InvalidScoreException e) {
e.printStackTrace();
}
System.out.println("프로그램 종료!");
728x90
반응형
'프로그래밍 언어 > JAVA' 카테고리의 다른 글
[JAVA] 자바 컬렉션 프레임워크 - Set 편 (0) | 2021.01.19 |
---|---|
[JAVA] 자바가 제공하는 패키지 (0) | 2021.01.19 |
[JAVA] 자바의 인터페이스 Interface (0) | 2021.01.19 |
[JAVA] 자바의 상수 Constant (0) | 2021.01.19 |
[JAVA] 자바의 Static (0) | 2021.01.19 |