try-catch, printStackTrace(), getMessage()와 예외 처리 흐름
예외처리
실행 중의 '에러(심각한 오류)'는 프로그래머가 해결을 할 수 없지만, 예외는 처리를 해주어야 한다. 예외처리란 프로그램 실행 시 발생할 수 있는 예상하지 못한 예외의 발생에 대비한 코드를 작성하는 것이다. 예외 처리는 예외 발생에 의한 프로그램의 비정상적 종료를 예방하고, 정상적인 실행상태를 유지하기 위함이다.
try-catch-finally문 : try-catch-finally문은 자바에서 예외 처리를 위해 사용되는 구문이다.
try블록: 예외가 발생할 수 있는 코드를 블럭 내에 작성하고, 이 블록 안에서 예외가 발생하면 제어 흐름은 try문 아래에 있는 catch 블록 중 하나로 이동된다.
catch블록: try에서 예외가 발생하면 해당하는 catch 블록으로 제어 흐름이 이동한다. 예외 타입과 일치하는 catch 블록은 해당 예외를 잡아서 예외를 처리하는 코드를 작성한다.
finally 블록(선택사항) : finally 블록은 예외 발생 여부와 관계없이 항상 실행되어야 하는 코드를 포함하고 있으며, 필수로 작성해야하는 부분은 아니다. 그러나 예외 처리 이후에 반드시 실행해야 하는 코드가 있을 경우에는 유용하다.
try-catch-finally 기본 예시 코드
try { // 예외가 발생할 수 있는 코드를 try 블록 내에 작성
int i = 0;
int j = 3 / i; // 0으로 나눌 수 없음. ArithmeticException 발생
System.out.println("code1");
} catch (ArithmeticException e) { //ArithmeticException 예외를 잡아 참조변수 e에 할당
System.out.println("code2"); // 예외 처리 코드
} finally { // exception 발생과 관계 없이 실행되는 block
System.out.println("꼭 실행 코드!!");
}
System.out.println("code3");
}
출력 결과
code2
꼭 실행 코드!!
code3
catch문을 여러 개 작성하는 방법
try {
// exception 발생 가능 코드
} catch (ArrayIndexOutOfBoundsException e) {
// exception 처리 코드
} catch (NumberFormatException e) {
// exception 처리 코드
}
try {
} catch (NullPointerException | ClassCastException | NumberFormatException e) {
// exception 처리 코드
}
printStackTrace()와 getMessage()
일반적으로 예외가 발생했을 때, 생성되는 예외 클래스의 인스턴스에는 발생한 예외에 대한 정보가 담겨있다. 이 정보를 getMessage()와 printStackTrace()를 통해서 얻을 수 있다.
메소드 | 설명 |
printStackTrace() | 메소드의 이름처럼, 예외 발생 당시의 호출스택(Call Stack)에 있었던 메서드를 추적해서 메소드 정보와 예외 메시지를 화면에 출력한다. |
getMessage() | 발생한 예외클래스의 인스턴스에 저장된 메시지를 얻을 수 있다. |
예시
public static void main(String[] args) {
method();
}
public static void method(){
try {
int i = 0;
int j = 3 / i; // 예외 발생.
} catch (ArithmeticException e) {
e.printStackTrace(); // 호출된 메소드
System.out.println("예외 메세지 : "+e.getMessage()); // by zero 출력
}
}
위 출력 결과에서 printStackTrace에 의해서 출력된 예외 종류'java.lang.ArithmeticException' 와 예외 메시지 '/ by zero'를 얻고 호출 스택에 있었던 메서드의 정보를 반환받은 것을 확인 할 수 있다
'at ch11exception.lecture.C05printStrackTrace.method(C05printStrackTrace.java:10)'
'at ch11exception.lecture.C05printStrackTrace.main(C05printStrackTrace.java:5)'
그리고 getMessage() 메소드를 통해 발생한 예외클래스의 인스턴스에 저장된 메시지를 얻을 수 있다. ' 예외 메세지: /by zero'
예외 발생과 예외 처리의 전반적인 흐름
1. 예외 발생: 실행 중 예외 상황이 발생하면, 해당 예외는 JVM 내에서 해당 클래스의 인스턴스로 생성.
- 예를 들어, ArithmeticException이 발생한 경우, ArithmeticException 인스턴스가 JVM에서 생성된다.
2. 예외 전달: 예외 발생 지점에서 발생한 예외는 실행 흐름에 따라 try 블록 내에 있는 catch 블록으로 전달한다.
3. 예외 처리: 선택된 catch 블록애소 얭하 인스턴스를 JVM으로부터 전달받아 예외에 대한 처리를 수행한다.
4. 예외 처리 후 실행: catch 블록이 실행되면 그 다음의 코드 블록이나 finally 블록 등으로 실행 흐름이 이동한다.
5.finally 블록의 실행: 예외가 발생하거나, 발생하지 않아도 finally 블록은 항상 실행된다. 주로 리소스 해제와 관련된 작업을 수행하는데 사용된다.
6. 예외 전파 : 만약 catch 블록에서 예외를 처리하지 않고 다시 'throw'하는 경우, 해당 예외는 '상위 호출 스택' 프레임으로 전파된다. 이 과정에서 최종적으로 예외를 처리할 수 있는 catch 블록을 찾게되고 최종적으로 예외를 처리할 수 있는 catch블록이 없다면, 프로그램은 강제 종료될 수 있다.
try-catch 블럭 흐름 정리
try-catch 블럭 | catch 블럭 |
1. 예외가 발생한 문장이 try블럭에 포함되어 있다면, 이 예외를 처리할 수 있는 catch블럭이 있는지 탐색한다. 2. 순차적으로 catch블럭들을 탐색하면서, catch 블럭 매개변수 영역 내에 선언된 참조 변수(예: (Exception e)의 종류와 생성된 예외 클래스의 인스턴스에 instanceOf 연산자를 이용해서 감시한다. 3. 검사 결과가 true인 catch 블럭을 만날 때까지 타입 검사를 이어나간다. 4. 검사 결과가 true인 catch 블럭을 찾게되면 블럭에 있는 문장들을 모두 수행한 후에 try-catch문을 빠져나가고 예외는 처리된다. (검사 결과가 true인 catch블럭이 하나도 없으면 예외는 처리되지 않는다.) |
-매개변수 선언 영역(괄호 () )내에 처리하고자 하는 예외와 같은 타입의 참조 변수를 하나 선언 -예외가 발생할 경우, 발생한 예외에 해당하는 클래스의 인스턴스가 만들어진다. - 예를들어, ArithmeticException이 발생한 경우 ArithmeticException 인스턴스가 생성된다. |