예외 처리 - 2

김나영·2023년 6월 15일
0

Java 문법 종합반

목록 보기
17/21

1. 예외 클래스 구조 이해하기

1) Checked Exception

  • 우리가 사전에 체크한 Exception

  • 우리가 예외 처리를 안 해 놓으면 컴파일 시 오류 발생 (try-catch로 감씨줬는지 확인)

2) Unchecked Exception

  • 그런 게 안 되어 있는 것

  • 런타임 때 발생하기 때문에 예측 불가

3) 자바의 Throwable Class

  • 시작은 모든 객체의 원형인 Object 클래스에서 시작

  • “문제 상황”을 뜻하는 Throwable 클래스가 Object 클래스를 상속

  • Throwable 클래스의 자식으로 앞서배운 에러(Error)와 예외(Exception) 클래스 존재

  • 에러(Error) 클래스와 예외(Exception) 클래스는 각각 IOError 클래스, RuntimeException 클래스와 같이 구분하여 처리

Exception 클래스 구조

  • RuntimeException을 상속한 예외들은 UncheckedException

  • 상속하지 않은 예외들은 CheckedException으로 구현되어 있음

  • Checked Exception에 속하는 에러 구현체들은 핸들링 하지 않으면 컴파일 에러가 발생하는 대신, 컴파일이 됐다면 100% 복구가 가능한 에러


2. Chained Exception

  • 연결된 예외

  • 예외는 다른 예외를 유발할 수 있음

    • 예외 A가 예외 B를 발생시켰다면, 예외 A는 B의 원인 예외
  • 원인 예외를 새로운 예외에 등록한 후 다시 새로운 예외를 발생시키는데, 이를 예외 연결이라고 함

❓ 왜 연결할까 ❓

  • 여러 가지 예외를 하나의 큰 분류의 예외로 묶어서 다루기 위함(어떤 특정한 문제에 대해서 예외 상황이 발생했을 때 이 예외 상황의 원인이 하나가 아니라 여러개일수도 있기 때문에)

  • checked exception을 unchecked exception으로 포장(Wrapping)하는데 유용하게 사용(코드를 줄이기 위해서)

  • 원인 예외를 다루기 위한 메소드

    • initCause() : 지정한 예외를 원인 예외로 등록하는 메소드
    • getCause() : 원인 예외를 반환하는 메소드
throw new RuntimeException(new Exception("이것이 진짜 예외 이유 입니다."));
  • =new Exception을 감싸서 RuntimeException안에 넣음으로써(chaining) 한 줄로 끝냄

  • 즉, checked exception을 감싸서 unchecked exception안에 넣음

// 연결된 예외 
public class main {

    public static void main(String[] args) {
        try {
            // 예외 생성
            NumberFormatException ex = new NumberFormatException("가짜 예외이유");

            // 원인 예외 설정(지정한 예외를 원인 예외로 등록)
            ex.initCause(new NullPointerException("진짜 예외이유"));

            // 예외를 직접 던집니다.
            throw ex;
        } catch (NumberFormatException ex) {
            // 예외 로그 출력
            ex.printStackTrace();
            // 예외 원인 조회 후 출력
            ex.getCause().printStackTrace(); // 원인에 대한 tracking이 편함
        }
    }
}
  • catch문으로 잡게 되면 initCause 해준 내용은 getCause로 잡을 수 있음

3. 실제 예외 처리하는 방법

  • 예외 복구, 예외 처리 회피, 예외 전환

1) 예외 복구하기

public String getDataFromAnotherServer(String dataPath) {
		try {
				return anotherServerClient.getData(dataPath).toString();
		} catch (GetDataException e) {
				return defaultData; // 정상적인 데이터 또는 defaultData를 반환함으로써 정상 상태로 복구
		}
}
  • 실제로 try-catch로 예외를 처리하고 프로그램을 정상 상태로 복구하는 방법

  • 가장 기본적인 방식

  • 현실적으로 복구가 가능한 상황이 아닌 경우가 많거나 최소한의 대응만 가능한 경우가 많기 때문에 자주 사용하지는 않음

2) 예외 처리 회피하기

public void someMethod() throws Exception { ... }

public void someIrresponsibleMethod() throws Exception {
		this.someMethod(); 
} // this.someMethod()를 호출하게 됐을 떼 Exception이 발생하면 throws Exception으로 흘러감
  • someMethod()에서 발생시킨 에러가 someIrresponsibleMethod()의 throws를 통해서 그대로 다시 흘러나감

  • 관심사를 분리해서 한 레이어에서 처리하기 위해서 에러를 회피해서 그대로 흘러 보내는 경우도 존재

3) 예외 전환하기

public void someMethod() throws IOException { ... }

public void someResponsibleMethod() throws MoreSpecificException {
		try { // someMethod() 오류가 발생하면 catch문(IOException)으로 잡힘
             // throws IOException으로 잡아놨기 때문에
			this.someMethod(); 
		} catch (IOException e) {
			throw new MoreSpecificException(e.getMessage()); // 그대로 처리하지 않고 다시 throw
		} // MoreSpecificException이라는 새로운 Exception을 만들어서 던짐
}
  • 예외처리 회피하기 방법과 비슷

  • 예외처리 회피하기보다 조금 더 적절한 예외를 던져주는 경우

  • RuntimeException처럼 일괄적으로 처리하기 편한 예외로 바꿔서 던지고 싶은 경우 사용

0개의 댓글