예외처리 |
프로그램이 실행 중 어떤 원인에 의해서 오작동을 하거나 비정상적으로 종료되는 경우가 있다. 이러한 결과를 초래하는 원인을 프로그램 에러 또는 오류라고 한다.
컴파일 에러: 컴파일 시에 발생하는 에러
런타임 에러: 실행 시에 발생하는 에러
논리적 에러: 실행은 되지만, 의도와 다르게 동작하는 것
에러: 프로그램 코드에 의해서 수습될 수 없는 심각한 오류
예외: 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류
예외 클래스의 계층구조
- 예외 클래스 계층도
- Exception클래스와 RutimeException클래스 중심의 상속 계층도
Exception클래스들 //사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외
RuntimeException클래스들 //프로그래머의 실수로 발생하는 예외
try-catch문 |
예외처리의 정의
- 프로그램 실행 시 발생할 수 있는 예외에 대비한 코드를 작성하는 것
예외처리의 목적
- 프로그램의 비정상 종료를 막고, 정상적인 실행상태를 유지하는 것
try-catch문의 형태
- 하나의 try블럭 다음에는 여러 종류의 예외를 처리핳 수 있도록 하나 이상의 catch블럭이 올 수 있으며, 이 중 발생한 예외의 종류와 일치하는 단 한 개의 catch블럭만 수행된다.
try {
//예외가 발생할 가능성이 있는 문장들을 넣는다.
}catch(Exception1 e1) {
//Exception1이 발생했을 경우, 이를 처리하기 위한 문장을 적는다.
}catch(Exception2 e2) {
//Exception2이 발생했을 경우, 이를 처리하기 위한 문장을 적는다.
}
try-catch문에서의 흐름
- try블럭 내에서 예외가 발생한 경우
1) 발생한 예외와 일치하는 catch블럭이 있는지 확인한다.
2) 일치하는 catch블럭을 찾게 되면, 그 catch블럭 내의 문장들을 수행하고 전체 try-catch문을 빠져나가서 그 다음 문장을 계속해서 수행한다. 만일 일치하는 catch블럭을 찾지 못하면, 예외는 처리되지 못한다.
- try블럭 내에서 예외가 발생하지 않은 경우
1) catch블럭을 거치지 않고 전체 try-catch문을 빠져나가서 수행을 계속한다.
- 모든 예외 클래스는 Exception클래스의 자손이므로, catch블럭의 괄호()에 Exception클래스 타입의 참조변수를 선언해 놓으면 어떤 종류의 예외가 발생하더라도 이 catch블럭에 의해서 처리된다.
printStackTrace()와 getMessage()
예외가 발생했을 때 생성되는 예외 클래스의 인스턴스에는 발생한 예외에 대한 정보가 담겨 있으며, 해당 함수 등을 이용해 정보를 얻을 수 있다. catch블럭 내에서만 사용 가능.
- printStackTrace()
예외발생 당시의 호출스택(Call Stack)에 있었던 메서드의 정보와 예외 메시지를 화면에 출력한다.
ex) e.printStackTrace();
- getMessage()
발생한 예외클래스의 인스턴스에 저장된 메시지를 얻을 수 있다.
ex) ae.getMessage();
멀티 catch블럭
JDK1.7부터 여러 catch블럭을 '|'기호를 이용해서, 하나의 catch블럭으로 합칠 수 있게 되었으며, 이를 '멀티 catch블럭'이라 한다. 만일 멀티 catch블럭의 '|'기호로 연결된 예외 클래스가 조상과 자손의 관계에 있다면 컴파일 에러가 발생 한다.
try{ //일반 catch블럭
...
} catch (ExceptionA e){
e.printStackTrace();
} catch (ExceptionB e2){
e2.printStackTrace();
}
try{ //멀티 catch블럭
...
} catch (ExceptionA | ExceptionB e){
e.printStackTrace();
}
예외 발생시키기
키워드 throw를 사용해서 프로그래머가 고의로 예외를 발생시킬 수 있으며, 방법은 아래의 순서를 따르면 된다.
1. 먼저, 연산자 new를 이용해서 발생시키려는 예외 클래스의 객체를 만든 다음
Exception e = new Exception("문자열");
2. 키워드 throw를 이용해서 예외를 발생시킨다.
throw e;
//형태1
Exception e = new Exception("문자열");
throw e;
//형태 2
throw new Exception("문자열");
RuntimeException클래스에 해당하는 예외는 프로그래머에 의해 실수로 발생하는 것들이기 때문에 예외처리를 강제하지 않는다. 하지만 Exception의 경우 강제 됨
RuntimeException 클래스 - unckecked예외
Exception 클래스 - ckecked예외
메서드에 예외 선언하기
void method() throws Exception1, Exception2, ... ExceptionN{
//메서드의 내용
}
자동 자원 반환 - try-with-resources문
JDK1.7부터 try-with-resources문이라는 try-catch문의 변형이 새로 추가되었다. try-with-resources문의 괄호 ()안에 객체를 생성하는 문장을 넣으면, 이 객체는 따로 close()를 호출하지 않아도 try블럭을 벗어나는 순간 자동적으로 close()가 호출된다. 그 다음에 catch블럭 또는 finally블럭이 수행된다.
public class TryWithResourceEx {
public static void main(String[] args) {
try(CloseableResource cr = new CloseableResource()){
cr.exceptionWork(false);
}catch(WorkException e){
e.printStackTrace();
}catch(CloseException e){
e.printStackTrace();
}
}
}
class CloseableResource implements AutoCloseable{
public void exceptionWork(boolean exception) throws WorkException{
System.out.println("exception()");
}
public void close() throws CloseException{
System.out.println("close()");
}
}
사용자정의 예외 만들기
기존의 정의된 예외 클래스 외에 필요에 따라 프로그래머가 새로운 예외 클래스를 정의하여 사용할 수 있다. 보통 Exception클래스 또는 RuntimeException클래스로부터 상속받아 클래스를 만들지만, 필요에 따라서 알맞은 예외 클래스를 선택할 수 있다.
class MyException extends Exception{
private final int ERR_CODE;
MyException(String msg, int errCode){
super(msg);
ERR_CODE = errCode;
}
MyException(String msg){
this(msg, 100);
}
public int getErrCode(){
return ERR_CODE;
}
}
예외 되던지기(exception re-throwing)
한 메서드에서 발생할 수 있는 예외가 여럿인 경우, 몇 개는 try-catch문을 통해서 메서드 내에서 자체적으로 처리하고, 그 나머지는 선언부에 지정하여 호출한 메서드에서 처리하도록 함으로써, 양쪽에서 나눠서 처리되도록 할 수 있다.
public class ExceptionEx{
public static void main(String[] args) {
try {
method();
} catch (Exception e) {
System.out.println("main메서드에서 예외 처리");
}
}
static void method() throws Exception{
try {
throw new Exception();
}catch(Exception e){
System.out.println("method메서드에서 예외처리");
throw e;
}
}
}
//method메서드에서 예외처리
//main메서드에서 예외 처리
연결된 예외(chained exception)
한 예외가 다른 예외를 발생시킬 수도 있다. 예를 들어 예외 A가 예외 B를 발생시켰다면, A를 B의 '원인 예외(cause exception)'라고 한다.
ie.initCause(e) //ie의 원인예외를 e로 지정
Throwable initCause(Throwable cause) //지정한 예외를 원인 예외로 등록
Throwable getCause() //원인 예외를 반환
- 원인 예외로 등록해서 다시 예외를 발생 시키는 이유
1) 여러가지 예외를 하나의 큰 분류의 예외로 묶어서 다루기 위해서이다.
2) checked예외를 unchecked예외로 바꿀 수 있도록 하기 위함
'프로그래밍 > JAVA' 카테고리의 다른 글
[JAVA 이론] 날짜와 시간 & 형식화 (0) | 2022.02.18 |
---|---|
[JAVA 이론] java.lang package & util classes (0) | 2022.01.27 |
[JAVA 이론] 클래스(추상, 인터페이스, 내부, 익명) (0) | 2022.01.27 |
[JAVA 이론] 다형성 (0) | 2022.01.27 |
[JAVA 이론] 상속 (0) | 2022.01.26 |