본문 바로가기
컴퓨터 프로그래밍/Java

[Java] 예외처리

by 한33 2024. 7. 30.

오류와 예외의 차이

  • 오류는 일반적으로 회복이 불가능한 문제
    • 시스템 레벨에서, 주로 환경적인 이유로 발생
  • 예외는 일반적으로 회복이 가능한 문제
    • 그 예외가 발생할 수 있다는 것을 인지하고, 대응했을 것. 아니라면 해야한다. 이를 대응하는 것이 예외처리

 

예외의 종류

코드 실행 관점에서 예외의 종류

  • 컴파일 에러 (예외)
    • 대부분 자바 프로그래밍 언어의 규칙을 지키지 않아서 발생
    • 그냥 다시 문법에 맞게 작성하면 됨
  • 런타임 에러 (예외)
    • 주로 다루게 될 에러 (예외)
    • 문법적인 오류는 아니라서 컴파일은 잘 되었지만, 프로그램이 실행 도중 마딱드리게 되는 예외

 

예외처리 관점에서 예외의 종류

  • 확인된 예외 ( Checked Exception )
    • 컴파일 시점에 확인하는 예외
    • 반드시 예외 처리를 해줘야함
  • 미확인된 예외 ( Unchecked Exception )
    • 런타임 시점에 확인되는 예외
    • 예외처리가 필수는 아님

예외 발생과 try-catch, finally 문

class OurBadException extends Exception {
    public OurBadException() {
        super("위험한 행동을 하면 예외처리를 꼭 해야합니다!");
    }
}

 

우선 Exception 클래스를 부모클래스로 둔 OurBadException 클래스를 생성해서 위와 같이 예외를 정의했다.

 

class OurClass {
    private final Boolean just = true;

    // 신규 문법 throws!
    public void thisMethodIsDangerous() throws OurBadException {
        if (just) {
            // 신규 문법 throw!
            throw new OurBadException();
        }
    }
}

 

just 이름으로  Boolean 변수를 선언했고 final 로 수정을 막았기 때문에 항상 true 로 무조건 예외를 처리할 수 있도록 했다.

 

 

우리가 thisMethodisDangerous 메서드를 선언하면서 이 메서드는 예외가 발생할 수 있는 위험한 코드라고 미리 인지 ( 예측 ) 했다. 그래서 우리는 이에 Flag 를 달아 확인하고자 해서 throws 문법을 OurbadException 클래스로 달아줬다.

 

그리고 실제로 문제가 있다면 throw new OurBadException(); 을 통해서 이 메서드가 위험하다고 알렸다.

 

public class StudyException {
    public static void main(String[] args) {
        OurClass ourClass = new OurClass();

        try {
            // 1. 위험한 메소드의 실행을 "시도" 해 봅니다.
            // "시도" 해보는 코드가 들어가는 블럭입니다.
            ourClass.thisMethodIsDangerous();
        } catch (OurBadException e) {
            // 2. 예외가 발생하면, "잡아서" handling 합니다.
            // 예외가 발생하는경우 "handling" 하는 코드가 들어가는 블럭입니다.
            // 즉 try 블럭 내의 구문을 실행하다가 예외가 발생하면
            // 예외가 발생한 줄에서 바로 코드 실행을 멈추고
            // 여기 있는 catch 블럭 내의 코드가 실행됩니다.
            System.out.println(e.getMessage());
        } finally {
            // 3. 예외의 발생 여부와 상관없이, 실행시켜야 하는 코드가 들어갑니다.
            // 무조건 실행되는 코드가 들어가는 블럭입니다.
            System.out.println("우리는 방금 예외를 handling 했습니다!");
        }

    }
}

 

우선 try 를 시도해본다. 만약 여기서 예외가 발생했다? 그럼 catch 로 잡아서 그 안에 코드를 실행시킨다.

이후 catch 진입 여부와는 상관없이 finally 내부 코드를 실행시킨다.

이를 예외를 handling 한다고 한다.

 

  • 여기서 catch () 괄호 안에는 어떤 예외 클래스를 받아서 처리할지 정의해주어야한다.
  • 모든 예외를 다 받고 싶으면 Exception 을 넣어주고 일부 예외만 받아서 처리하고 싶으면 위와 같이 해당 예외 클래스명을 넣어주면 된다.
  • 1개의 try 문에 여러 개의 catch 문을 사용해도 된다.

 

  • 위 예시는 Checked Exception 을 다룸
  • 메서드를 선언할 때 예외가 발생하는 위험한 메서드라는 것에 throws/throw 를 달아 알렸다.
  • 우리가 checked exception 을 정의하고 알렸으니 이 메서드를 사용할 때 예외처리를 하지 않으면 컴파일 에러가 발생한다.

예외 클래스 구조

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

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

 

RuntimeException  을 상속한 예외들은 UncheckedException, 반대로 상속하지 않은 예외들은 CheckedException 으로 구현


Chained Exception 

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

 

 

initCause() : 지정한 예외를 원인 예외로 등록하는 메서드

getCause() : 원인 예외를 반환하는 메서드

 

실제 예외 처리

1. 예외 복구하기

public String getDataFromAnotherServer(String dataPath) {
    try {
        return anotherServerClient.getData(dataPath).toString();
    } catch (GetDataException e) {
        return defaultData;
    }
}
  • try-catch 로 예외 처리하고 정상상태로 복구하는 방법
  • 가장 기본적인 방식이지만, 현실적으로 복구가 가능한 상황이 아닌 경우가 많거나 최소한의 대응만 가능한 경우가 많기 때문에 자주 사용되지는 않음

 

2. 예외 처리 회피하기

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

public void someIrresponsibleMethod() throws Exception {
    this.someMethod();
}

 

  • 이렇게 처리하면, someMethod()에서 발생한 에러가 someIrresponsibleMethod()의 throws를 통해서 그대로 다시 흘러나감 (물론 같은 객체 내에서 이런 일은 하지 않음.)
  • 관심사를 분리해서 한 레이어에서 처리하기 위해서 이렇게 에러를 회피해서 그대로 흘러 보내는 경우도 있음

 

3. 예외 전환하기

  • 해당 예외보다 좀 더 적절한 예외를 던져줌
  • RuntimeException 처럼 일괄적으로 처리하기 편한 예외로 바꿔서 던지고 싶은 경우에도 사용

 

'컴퓨터 프로그래밍 > Java' 카테고리의 다른 글

[Java] Collection 과 Wrapper 객체  (0) 2024.08.05
[Java] Generic  (0) 2024.08.04
[Java] 인터페이스  (0) 2024.07.30
[Java] 상속  (0) 2024.07.29
[Java] this와 this(), 접근 제어자, package와 import  (0) 2024.07.29