예외 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; |
| |
| |
| |
| |
| int[] arr = new int[3]; |
| |
| |
| String str = null; |
| |
| |
| Animal ani = new Dog(); |
| Cat cat = (Cat)ani; |
| |
| 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; |
| |
| |
| try { |
| System.out.println(num / num2); |
| |
| |
| System.out.println("try 문 종료"); |
| } catch(ArithmeticException e) { |
| |
| |
| System.out.println("0으로 나눌 수 없습니다!"); |
| } |
| |
| |
| System.out.println("프로그램 종료!"); |
두 가지 이상의 예외가 발생할 가능성이 있는 경우
두 가지 이상의 예외를 각각의 catch 블록에서 처리
- 두 개 이상의 catch 블럭을 작성하여 각 예외를 별도로 처리 단, 예외 발생 시 윗쪽 catch 블럭부터 아래쪽으로 순서대로 탐색
| System.out.println("프로그램 시작!"); |
| |
| try { |
| num2 = 0; |
| |
| |
| 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; |
| |
| |
| String str = null; |
| System.out.println(str.length()); |
| |
| |
| } catch (Exception e) { |
| System.out.println("모든 예외 처리!"); |
| |
| |
| } |
| |
| |
| |
| |
| |
| |
| System.out.println("프로그램 종료!"); |
try ~ catch ~ finally 블록
- try 블록에서 예외 발생 여부와 관계 없이 무조건 실행해야하는 문장들은 finally 블록 내에 기술함
- 예외가 발생하거나 발생하지 않아도 무조건 실행되며 심지어 return 문을 만나 메서드 실행이 종료될 때도 finally 블록 내의 코드를 실행한 후 종료
- 주로, 자원 반환을 위한 코드를 기술 ex. DB 접속 종료, 입출력 스트림 종료 등
기본 문법
| try { |
| |
| } catch(예외클래스명 변수명) { |
| |
| } finally { |
| |
| } |
| public static void exceptionMethod(int num) { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| try { |
| System.out.println("Code1 : num = " + num); |
| |
| int total = 1 / num; |
| |
| System.out.println("Code2 : 예외 발생 없음!"); |
| |
| return; |
| |
| |
| |
| } 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 { |
| |
| |
| |
| |
| |
| |
| 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 { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| 대리(); |
| } |
| |
| public static void 대리() throws SQLException, ClassNotFoundException { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| 사원(); |
| 사원2(); |
| } |
| |
| public static void 사원() throws SQLException { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| Connection con = DriverManager.getConnection(""); |
| |
| |
| |
| } |
| |
| public static void 사원2() throws ClassNotFoundException { |
| |
| Class.forName(""); |
| } |
| try { |
| 과장(); |
| } catch (Exception e) { |
| System.out.println("main() 메서드(사장)가 모든 예외 위임받아 처리!"); |
| } |
throw 키워드
- 개발자가 직접 예외를 발생시킬 때 사용
- 자바 문법에서 위반되지 않는 코드라도 강제로 예외 발생 가능
- 예외를 발생시킬 위치에 throw 키워드 뒤에 발생시킬 예외 클래스의 객체를 생성하여 강제로 예외를 발생시켜 던짐
| class InvalidScoreException extends Exception { |
| |
| |
| |
| public InvalidScoreException(String message) { |
| |
| super(message); |
| } |
| |
| } |
| public static void score(int score) throws Exception { |
| |
| |
| |
| if(score >= 0 && score <= 100) { |
| System.out.println("학점 계산!"); |
| } else { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| 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("프로그램 종료!"); |