개발 공부/Java & Spring

7. 예외처리(exception handling)

빵다희 2022. 11. 12. 23:27
프로그램 오류(에러)
: 프로그램이 실행 중 오작동을 하거나 비정상적으로 종료되는 경우를 초래하는 원인.
- 컴파일 에러(compile-time error) : 컴파일 할 때 발생하는 에러.
- 런타임 에러(runtime error) : 프로그램 실행 도중에 발생하는 에러.
- 논리적 에러(logical error) : 컴파일, 실행에는 이상없지만 의도와 다르게 동작하는 것.
에러(error)와 예외(exception)
: 자바에서 실행시 발행할 수 있는 프로그램 오류의 유형.
- 에러(error)         : 발생하면 프로그램 코드에 의해서 수습될 수 없는 심각한 오류.
                                 프로그램의 비정상적인 종료를 막을 수 없다.
                                 ex) OutOfMemoryError(메모리부족), StackOverflowError(스택오버플로우)...
- 예외(exception) : 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류. 
                                 발생하더라도 이에 적절한 코드를 미리 작성해놓으면 프로그램의 비정상적인 종료를 막을 수 있다.
예외 클래스의 계층구조

- 자바에서 실행 시 발생할 수 있는 오류(Exception과 Error)를 클래스로 정의.
- 모든 클래스의 조상은 Object이므로 Exception과 Error클래스도 Object클래스의 자손들이다.
- 모든 예외의 최고 조상은 Exception클래스이다. 

Exception클래스와 RuntimeException클래스 중심의 상속계층도

-RuntimeException클래스와 그 자손 클래스들 :  주로 프로그래머의 실수에 의해서 발생될 수 있는 예외들.
ex) 배열의 범위를 벗어남(ArrayIndexOutOfBoundsException), null에서 참조변수의 멤버를 호출(NullPointException), 클래스간의 형변환을 잘못함(ClassCastException), 정수를 0으로 나누려고 함(ArithmeticException) 등등..

- Exception클래스와 그 자손 클래스들 : 주로 외부의 영행을 발생할 수 있는 예외들. 프로그램 사용자들의 동작에 의해서 발생하는 경우가 많다. 
ex) 존재하지 않은 파일의 이름 입력(FileNotFoundException), 클래스의 이름을 잘못적기(classNotFoundException), 입력한 데이터 형식이 잘못된 경우(DataFormatException) 등등...

 

예외처리하기 - try-catch문
- 프로그램 실행 중 발생하는 에러는 어쩔 수 없지만, 예외는 프로그래머가 미리 처리를 해주어야한다.
- 예외처리의 정의  : 프로그램 실행 시 발생할 수 있는 예외에 대비한 코드를 작성하는 것.
- 예외처리의 목적 : 예외의 발생으로 인한 프로그램의 비정상 종료를 막고, 정상적인 실행상태를 유지할 수 있도록 하는 것.
- 처리되지 못한 예외는 JVM의 '예외처리기'가 받아서 예외의 원인을 화면에 출력한다. 
(* 예외처리기 : 예외 처리기는 예외가 발생하면 예외 객체를 생성시키고 예외가 발생된 메소드에서 ERROR 를 출력하고, 그 메소드를 호출한 메소드에게 예외를 반환한다. 출처 : https://herojune.tistory.com/2)
/* try-catch문 예시 */

try {
	// 예외가 발생할 가능성이 있는 문장들을 넣는다. 
} catch (Exception1 e1) {
	// Exception1이 발생했을 경우, 이를 처리하기 위한 문장을 적는다.
} catch (Exception2 e2) {
	// Exception2이 발생했을 경우, 이를 처리하기 위한 문장을 적는다.
}

- 하나의 try블럭 다음에는 여러 종류의 예외를 처리할 수 있도록 하나 이상의 catch블럭이 올 수 있으며, 그 중 발생한 예외의 종류와 일치하는 단 한개의 catch블럭만 수행된다.

- 발생한 예외의 종류와 일치하는 catch블럭이 없으면 예외는 처리되지 않는다.

- if문과 달리, try블럭이나 catch블럭 내에 포함된 문장이 하나뿐이어도 괄호 { }를 생략할 수 없다.

( catch(Exception e) ~~예외처리 코드 --> 이렇게 작성 불가  )

 

class ExceptionEx1 {
	public static void main(String[] args) {
    	try {
        	try {  } catch (Exception e) {  }
        } catch (Exception e) {
         // 에러. 변수 e가 중복 선언되었다. 
        	try {  } catch (Exception e) {  }      
        }
    }
}

- 하나의 메서드 내에 여러 개의 try-catch문이 사용될 수 있으며, try블럭 또는 catch블럭에 또 다른 try-catch문이 포함될 수 있다. 

- catch블럭내에 또 try-catch문이 포함될 경우 같은 이름의 참조변수를 사용하면 안된다. 각 catch블럭에 선언된 두 참조변수의 영역이 서로 겹치므로 다른 이름을 사용해야한다. 

 

try-catch문에서의 흐름
예외 발생 유무에 따라 문장의 실행순서가 다르다.
- try블럭 내에서 예외가 발생한 경우
 1. 발생한 예외와 일치하는 catch블럭이 있는지 확인한다.
 2. 일치하는 catch블럭을 찾게 되면, 그 catch블럭 내에 문장들을 수행하고 전체 try-catch문을 빠져나가서 그 다음 문장을 수행    한다.
 3. 만일 일치하는 catch블럭을 찾지 못하면, 예외는 처리되지 못한다. 

-try블럭 내에서 예외가 발생하지 않은 경우
catch블럭을 거치지 않고 전체 try-catch문을 빠져나가서 수행을 계속한다 .
Class ExceptionEx {
	public static void main(String args[]) {
    	System.out.println(1);
        System.out.println(2);
        try {
        	System.out.println(3);
            System.out.println(0/0); // 0으로 나눠서 고의로 에러 발생 시킴.
            // 에러가 발생한 이후에는 catch블럭의 코드가 실행되므로, 해당코드는 실행되지 않는다.
            System.out.println(4);   
        } catch (Exception e) {
        	System.out.println(5);
        } // try-catch의 끝
        System.out.println(6);
    }
}

/*
 실행결과 
 1
 2
 3
 5
 6

*/

* try블럭에서 예외가 발생하면, 예외가 발생한 위치 이후에 있는 try블럭의 문장들은 수행되지 않으므로, try블럭에 포함시킬 코드의 범위를 잘 선택해야한다. 

 

예외의 발생과 catch블럭
- catch블럭의 괄호() 내에는 처리하고자 하는 예외와 같은 타입의 참조변수 하나를 선언해야한다.
- 예외가 발생하면, 발생한 예외에 해당하는 클래스의 인스턴스가 만들어진다. 
- 첫 번째 catch블럭부터 차례로 내려가면서 catch블럭의 괄호()내에 선언된 참조변수의 종류와 생성된 예외클래스의 인스턴스에 instanceof연산자를 이용해서 검사결과가 true가 될 때 까지 계속 검사한다.
- true가 나오면 블럭안에 있는 문장들을 모두 수행한 후 try-catch문을 빠져나가고 예외가 처리되지만, true인 블럭이 하나도 없으면 예외는 처리되지 않는다. 
- 모든 예외 클래스는 Exception클래스의 자손이므로, catch블럭의 괄호()에 Exception클래스 타입의 참조변수를 선언해 놓으면 어떤 종류의 예외라도 이 catch블럭에서 처리된다.

 

printStackTrace()와 getMessage()
- 예외가 발생했을 때 생성되는 예외 클래스의 인스턴스에는 발생한 예외에 대한 정보가 담겨져 있는데 아래 메소드 호출을 통해 예외의 발생원인을 확인 할 수 있다. 
- printStackTrace() : 예외발생 당시의 호출스택(Call Stack)에 있었던 메서드의 정보와 예외메시지를 화면에 출력한다. 
- getMessage() : 발생한 예외클래스의 인스턴스에 저장된 메시지를 얻을 수 있다. 
- printStackTrace(PrintStream s) ,printStackTrace(PrintWriter s)를 사용하면 발생한 예외에 대한 정보를 파일에 저장할 수도 있다. 

 

멀티 catch블럭
- 멀티 catch 블럭은 JDK1.7부터 여러 catch블럭을 '|' 기호를 이용해서, 하나의 catch블럭으로 합치는 것을 말한다.
- 멀티 catch 블럭을 이용하면 중복된 코드를 줄일 수 있다.
- '|' 기호로 연결할 수 있는 예외 클래스의 개수에는 제한이 없다.
try {
	...
} catch (ParentException | ChildException e ) { // 에러! 조상과 자식의 관계
	e.printStackTrace();
} catch (ExceptionA | ExeptionB e) {
	e.methodA();   // 에러! 조상클래스가 아닌 ExceptionA에만 선언된 메소드는 호출 불가
}

* 멀티 catch 사용시 주의할 점

- '|' 기호로 연결된 예외클래스가 조상과 자손의 관계에 있다면 컴파일 에러가 발생한다. 이유는 자손의클래스와 같이 사용하면 그냥 조상클래스만 써주는 것과 똑같기 때문이다.  불필요한 코드는 제거하라는 의미에서 에러가 발생한다. 

- 멀티 catch블럭 내에서는 실제로 어떤 예외가 발생한 것인지 알 수 없기 때문에 '|' 기호로 연결된 예외 클래스들의 공통 분모인 조상 예외. 클래스에 선언된 멤버만 사용할 수 있다.

- 멀티 catch블럭에 선언된 참조변수 e는 상수이므로 값을 변경할 수 없다. 이유는 여러 catch블럭이 하나의 참조변수를 공유하기 때문이다. 

 

 

728x90
반응형

'개발 공부 > Java & Spring' 카테고리의 다른 글

9. Math클래스  (0) 2022.12.06
8. StringBuffer 클래스와 StringBuilder 클래스  (0) 2022.12.06
6. 내부 클래스(inner class)  (1) 2022.11.06
5. 제어자(modifier)  (0) 2022.10.24
4. package와 import  (0) 2022.10.23