JAVA_예외처리 정리 (자바의정석 8장)
예외처리 정의 : 프로그램 실행시 발생할 수 있는 예외의 발생에 대비한 코드를 작성하는 것.
예외처리 목적 : 예외처리를 통해 견고한 프로그램을 만들어 프로그램의 비정상 종료를 막고,
정상적인 실행상태를 유지하는 것. [ 프로그램이 중간에 종료되지 않게 해야한다 ]
본격적인 내용으로 들어가기에 앞서
컴파일러가 하는 일
- 문법체크
- 구문분석
- 최적화
- 자동코드추가
- 번역
오류에는 3가지 종류가 있다
- 컴파일에러 : 컴파일시 발생하는 에러 ( 실행자체가 안된다 )
- 런타임에러 : 실행시에 발생하는 에러
- 논리적에러 : 실행은 되지만, 의도한대로 동작하지 않는다
런타임 에러에는 2가지로 나뉜다
Error 와 Exception 으로 나뉘고
Error : 심각 [ 예시로는 OutOfMemory OOM 에러가 있다 ]
Exception : 덜 심각
Exception은 Exception의 자손 과 RuntimeException의 자손으로 나뉜다
Exception의 자손 : 필수처리 , 사용자의 실수에 의해서 발생
RuntimeExcepiton의 자손 : 선택처리 , 프로그래머의 실수에 의해서 발생한다
[ 예시로는 NullPointException / ArrayIndexOutOfBoundException 등이 있다. ]
예외를 처리하는 방식 3가지
- try - catch ( 직접처리 )
- 예외선언 ( 보고 )
- 은폐
try - catch 와 예외선언 둘 다 하는 양쪽에서 처리하는 방법도 존재하긴 한다.
예외 클래스의 계층구조
Exception 클래스부터 도식화한 그림
위에 그림에서 I/OException ( 입출력에러 ) / ClassNotFoundException ( 클래스가 존재하지 않음 ) 은 사용자실수에 대한 부분으로 필수처리 ( 처리하지 않으면 컴파일에러가 발생 )에 해당한다
색칠되어 있는 부분에 해당하는 ArithmeticException ( 산술계산 ) / ClassCastException ( 형변환주의 ) / NullPointerException ( 널포인트 ) / IndexOutOfBoundsException ( 배열범위 벗어나는 에러 ) 는 프로그래머 실수에 대한 부분으로 선택처리 ( 처리하지 않아도 컴파일이 가능하다 ) 에 해당한다
try - catch 문에서의 흐름
> try블럭 내에서 예외가 발생하는 경우,
1. 발생한 예외와 일치하는 catch블럭이 있는지 확인
2. 일치하는 catch블럭을 찾게 되면, 그 catch블럭 내의 문장들을 수행하고
전체 try - catch문을 빠져나가서 그 다음 문장을 계속해서 수행한다.
만일 일치하는 catch블럭을 찾지 못하면, 예외는 처리되지 못한다 ( 프로그램 비정상 종료 )
> try블럭 내에서 예외가 발생하지 않은 경우,
1. catch블럭을 거치지 않고 전체 try - catch문을 빠져나가서 수행을 계속한다.
예외발생 후에 코드가 실행이 되지 않는 경우에 대한 케이스이다.
고의로 산술에러를 발생시킨 다음 System.out.println(4); 에 대한 부분이 출력되지 않았는데
그 이유는 문제가 발생하면 그 뒤로 실행하는건 의미없다고 컴파일러가 판단하기 때문이다.
위 사진처럼 try - catch 문의 마지막에 Exception 클래스 타입의 참조변수를 선언한 catch블럭을 사용하면
어떤 종류의 예외가 발생하더라도 이 catch블럭에 의해 처리되도록 할 수 있다.
printStackTrace( ) 와 getMessage( )
printStackTrace( ) : 예외발생 당시의 호출스택( Call Stack )에 있었던 메서드의 정보와 예외 메시지를 화면에 출력
getMessage( ) : 발생한 예외클래스의 인스턴스에 저장된 메시지를 얻을 수 있음.
멀티 catch블럭
내용이 같은 catch블럭을 하나로 합친 것.
try {
} catch (ExceptionA e) {
e.printStackTrace();
} catch (Exception e2) {
e2.printStackTrace();
}
e 와 e2가 내용이 동일한데 이런식으로 코드를 고칠 수 있다.
try {
...
} catch ( ExceptionA | ExceptionB e ) {
e.printStackTrace();
}
예외 발생시키기
1. 먼저, 연산자 new를 이용해서 발생시키려는 예외 클래스의 객체를 만든 다음
Exception e = new Exception ("고의로 발생시켰음");
2. 키워드 throw를 이용해서 예외를 발생시킨다.
throw e;
컴파일러가 예외처리를 확인하지 않는 RuntimeException클래스들은 'unchecked예외' 라고 부른다
메서드에 예외 선언하기
try - catch문을 사용하는 것이 아닌 예외를 메서드에 선언하는 방법이다.
finally블럭
finally 블럭 : 예외의 발생여부에 상관없이 실행되어야할 코드를 포함시킬 목적으로 사용 \
catch블럭의 문장 수행 중에 return문을 만나도 finally블럭의 문장들은 수행된다.
예외처리를 강제하도록 한 이유:
프로그래밍 경험이 적은 사람들도 보다 견고한 프로그램을 작성할 수 있게 유도하기 위한 것이었는데, 자바가 탄생하던 때와 달리 프로그래밍 환경이 많이 달라졌다.
프로그래밍 환경이 달라진 만큼 필수적으로 처리해야만 할 것 같았던 예외들이 선택적으로 처리해도 되는 상황으로 바뀌는 경우가 종종 발생한다.
그래서 필요에 따라 예외처르이 여부를 선택할 수있는 'unchecked예외'가 강제적인 'checked예외'보다 더 환영받고 있다.
예외 되던지기(exception re-throwing)
예외를 처리한 후 다시 예외를 발생시키는 것.
호출한 메서드와 호출된 메서드 양쪽 모두에서 예외처리 하는 것을 말한다.
연결된 예외(chained exception)
예외관계도 상속에 말하는 관계처럼 상속과 포함으로 나뉜다.
2가지 상황이 있다
- 여러 예외를 묶어서 다루기
- 필수예외를 선택예외로 바꿀때
위 그림은 MemoryExceptin ( 필수예외 ) 필수 처리해야하는 에러를 RuntimeException ( 선택예외) 로 담아서
필수예외를 -> 선택예외로 바꾸는 것을 설명하는 그림이다.