[Java의 정석] 8장 예외처리 Exception Handling

이정규·2022년 3월 22일
0

Java의 정석

목록 보기
7/7

예외 처리

에러의 종류

  • 컴파일 에러
    컴파일 시에 발생하는 에러
  • 런타임 에러
    실행 시에 발생하는 에러
  • 논리적 에러
    실행은 되지만, 의도와 다르게 동작하는 것

에러와 예외

에러

프로그램 코드에 의해서 수습될 수 없는 심각한 오류

예외

프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류

예외 클래스의 계층 구조

모든 클래스의 조상은 Object이므로 Object가 갖고 있다.

여기서 예외의 최고 조상은 Exception 클래스 이다.

Exception클래스를 보면 두 그룹으로 나누어져 있다.

  1. Exception클래스와 그 자식들(RuntimeException과 자식들 제외)
    => 사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외이다.
    ex) FileNotFoundException, ClassNotFoundException, DataFormatException

  2. RuntimeException클래스와 그 자식들
    => 프로그래머의 실수로 발생하는 예외이다.
    ex) ArrayIndexOutOfBoundsException, NullPointerException, ClassCastException

Checked Exception

컴파일시에 에러가 난다. 그렇기 때문에 반드시 해당 예외에 대해서는 처리해야한다.

Unchecked Exception

실행시에 에러가 난다. 해당 예외 처리는 선택적으로 처리해도 된다.

예외처리하기

try-catch

try {
	// 예외가 발생할 수 있는 코드
} catch (Exception e1) {
	// e1에 대한 예외가 발생했을 때 예외처리
} catch (Exception e2) {
	// e2에 대한 예외가 발생했을 때 예외처리
} finally {
	// 예외의 발생여부에 상관없이, 실행되는 코드
}

흐름

  1. try블럭에서 예외가 발생한다.
  2. 발생한 예외와 일치하는 catch블럭을 찾는다.
    => 이 때, instanceof 연산자를 이용해 발생한 예외의 인스턴스 타입과 일치하는 것을 찾는다.
  3. 일치하는 catch블럭을 찾으면 수행한다. 없으면, 예외는 처리되지 않는다.

예외 정보 출력

  • printStackTrace()
    예외 발생 당시의 호출스택에 있었던 메소드의 정보와 예외 메시지를 화면에 출력한다.
  • getMessage()
    발생한 예외 클래스의 인스턴스에 저장된 메시지를 볼 수 있다.

멀티 catch 블럭

try {
	...
} catch (ExceptionA | ExceptionB e {
	...
}

JDK1.7부터 다음과 같이 | 를 이용하여 하나의 catch블럭으로 합칠 수 있다.

예외 발생시키기

throw를 이용하여 고의로 예외를 발생시킬 수 있다.

throw new Exception("고의로 발생시킨 예외메시지");

메소드에 예외 선언하기

void method() throws Exception1, Exception2, ... ExceptionN {
	...
}

throws를 적으면 메서드에 이러한 예외가 나타날 수 있다는 것을 암시한다.

이렇게 발생할 가능성이 있는 예외를 메소드 선언부에 명시하여 해당 메소드를 사용하는 쪽에서 이에 대한 처리를 하도록 강요할 수 있다.

주의할 점

메소드에 예외를 선언할 때, RuntimeException 즉, Unchecked Exception에 대한 내용은 선언하지 않는다.

보통 반드시 처리해야하는 Checked Exception에 대한 내용만 선언한다.

try-with-resource

JDK1.7부터 추가된 구문이다.

try (FileInputStream fis = new FileInputStream("score.dat");
	 DataInputStream dis = new DataInputStream(fis)) {
 	...
} catch (EOFException e) {
	...
} catch (IOException ie) {
	...
}

이것과 같이 try 괄호 안에 객체를 생성하는 문장을 넣는다.

그러면 해당 객체들은 try블럭을 벗어나는 순간 자동적으로 close()를 호출해 자원을 반납한다.

사용자 정의 예외 만들기

class MyException extends Exception {
	MyException(String msg) {
    	super(msg);
    }
}

Exception의 생성자로는 예외처리 메시지가 들어간다.

연결된 예외

만약 예외 A가 예외 B를 발생시킨다면 A는 B의 원인 예외라고한다.

throwable 클래스에는 다음과 같은 함수가 존재한다.

public synchronized Throwable initCause(Throwable cause) {
	if (this.cause != this)
		throw new IllegalStateException("Can't overwrite cause with " +
                                            Objects.toString(cause, "a null"), this);
	if (cause == this)
		throw new IllegalArgumentException("Self-causation not permitted", this);
	this.cause = cause;
	return this;
}

함수인자로 cause가 있는데 여기로 A때문에 B가 발생된다면

try {

} catch (ExceptionA ae) {
	ExceptionB be = new ExceptionB("예외");
    be.initCause(ae);
    throw ie;
}

다음과 같이 be의 원인으로 ae를 집어넣을 수 있다.
이를 확인하는 방법은
be.getCause() 로 가능하다.

참고
https://itmining.tistory.com/9

profile
강한 백엔드 개발자가 되기 위한 여정

0개의 댓글