코린이의 소소한 공부노트

예외 처리 (2) - 메서드에 예외 선언하기, finally 블록 본문

Java

예외 처리 (2) - 메서드에 예외 선언하기, finally 블록

무지맘 2022. 5. 26. 17:22

예외를 처리하는 방법에는 크게 3가지 정도가 있다.

1. try-catch문: 예외가 발생한 곳에서 직접 처리하는 방법

  - 2022.05.19 - [Java] - 프로그램 오류의 종류와 예외 처리

2. 예외 선언하기: 예외를 다른 곳에 떠넘기는(알리는) 방법

3. 은폐: 빈 catch 블록을 선언해 예외를 덮거나 무시하는 방법

  - 사용하지 않는 것을 원칙으로 하고 있으나

  - 빅데이터 처리 등 이상한 정보를 처리하지 않아야 할 때 사용

 

이번 글에서 볼 것은 예외 선언하기이다.

메서드에 예외를 선언한다는 것은 메서드 호출 시 발생 가능한 예외를 호출하는 쪽에 알리는 것을 말한다.

1. 선언 방법

void method() throws Exception1, Exception2, ..., ExceptionN{
    // 메서드 내용
}

// 참고: throw는 예외를 발생시키는 키워드

  - 메서드 선언부에 throws를 이용해서 method()를 사용 시 Exception1, ..., ExceptionN이 발생할 수 있다는 것을 알려준다.

2. 선언 예시

 1) 예외 선언 개수 비교

// 예시1: 메서드에서 Exception과 그 자손 예외 발생 가능
void method() throws Exception{
    // 메서드 내용
}

// 예시2: 메서드에서 예외가 3개 발생 가능
void method() throws Exception1, Exception2, Exception3{
   // 메서드 내용
}

  - 예시1에는 예외가 1개, 예시2에서는 예외가 3개 선언

  - Exception은 모든 예외의 조상이므로 실제로 선언된 예외의 개수는 예시1이 더 많음

  - 오버라이딩할 때 예외 선언 개수 체크

 2) 메서드 호출 시 발생한 예외 알리기(떠넘기기)

// 예시3: 게임 설치
static void startInstall() throws SpaceException, MemoryException{
    if(!enoughSpace())
        throw new SpaceException("설치 공간이 부족합니다.");
    if(!enoughMemory())
        throw new MemoryException("메모리가 부족합니다.");
}

  - 설치 공간이 부족 -> 메서드 호출한 쪽에 SpaceException을 알림

  - 메모리가 부족 -> 메서드 호출한 쪽에 MemoryException을 알림

 3) 발생 가능한 모든 예외를 선언하지 않는다.

// 예시4: 자바 API문서에서 가져온 wait()의 설명
public final void wait()
    throws InterruptedException // 예외 선언
// 중략
Throws:
IllegalMonitorStateException - 생략
InterruptedException - 생략

  - wait() 메서드 선언부에 InterruptedException이 선언되어있다.

  - 메서드 설명에서 발생 가능한 예외를 살펴보니 IllegalMonitorStateException도 있다.

  - InterruptedException은 Exception의 자손이고, IllegalMonitorStateException은 RuntimeException의 자손이다.

  - RuntimeException과 그 자손은 메서드에 예외 선언을 하지 않는 게 일반적이다.

  - 그래서 checked 예외인 InterruptedException은 예외 선언을 한 것이고, unchecked 예외인 IllegalMonitorStateException은 예외 선언을 하지 않은 것이다.

 4) 예외 선언된 메서드 호출 시 호출 스택에서 일어나는 일

class Test {
    public static void main(String[] args) throws Exception {
        method1(); // 같은 클래스내의 static멤버이므로 객체생성없이 직접 호출가능
    }
    
    static void method1() throws Exception { method2(); }
    
    static void method2() throws Exception { throw new Exception(); }
}

// 결과
Exception in thread "main" java.lang.Exception
    at Test.method2(Test.java:8)
    at Test.method1(Test.java:6)
    at Test.main(Test.java:3)

  - 메서드에 예외 선언만 되어있지 try-catch문이 없기 때문에 프로그램이 비정상 종료가 된다.

 5) 파일 만들기

import java.io.File;

class Test {
    public static void main(String[] args) {
        try {
            File f = createFile("testfile.txt"); // 파일 이름
            System.out.println(f.getName() + "파일이 성공적으로 생성되었습니다.");
        } catch(Exception e) {
            System.out.println(e.getMessage() + " 다시 입력해 주시기 바랍니다.");
        }
    }
    
    static File createFile(String fileName) throws Exception {
        if(fileName==null || fileName.equals(""))
            throw new Exception("파일이름이 유효하지 않습니다.");
        // 파일 이름이 유효할때만 아래 문장들이 실행된다.
        File f = new File(fileName); // File클래스 객체 생성
        f.createNewFile(); // 메서드를 이용해 실제 파일 생성
        return f;
    }
}

// 결과
testfile.txt파일이 성공적으로 생성되었습니다.

// 파일 이름이 "" (빈 문자열)일때의 결과
파일이름이 유효하지 않습니다. 다시 입력해 주시기 바랍니다.

  - 파일 이름("testfile.txt")이 유효하기 때문에 파일이 생성된다. 이때 만들어진 파일은 해당 자바 파일이 있는 프로젝트 루트 폴더에 생긴다.

  - 파일 이름이 빈 문자열일 경우, createFile()에서 예외 발생시켜 main()에 떠넘긴다. 그러면 main()에서 이를 받아서 catch문에서 처리한다.

필자의 연습폴더에 testfile.txt이 생성된 모습

 

try-catch문은 try 블록을 실행하다가

1. 예외가 발생하면

 1) 알맞은 catch 블록을 찾아 실행시킨다.

 2) 맞는 catch가 없다면 예외가 발생한 문장 전까지만 수행하고 프로그램이 비정상 종료된다.

2. 예외가 발생하지 않는다면 try 블록을 모두 수행한 후 try-catch문을 빠져나온다.

이때, 예외 발생 여부와 상관없이 무조건 수행하는 문장을 추가하고 싶을 때 사용하는 것이 finally 블록이다.

try{
    // 예외 발생 가능성이 있는 문장들
} catch(Exception e){
    // 예외 처리 문장들
} finally{
    // 예외 발생 여부와 상관 없이 수행하는 문장들
    // try-catch문의 맨 마지막에 위치
    // try 블록에 return이 있어도 이 블록은 실행됨
}

 

[쿠키글] 메서드 오버라이딩 가능 조건

1. 메서드의 선언부 일치

2. 조상의 메서드보다 넓거나 같은 범위의 접근 제어자 사용(public > default > protected > privata)

3. 조상의 메서드보다 적게 예외 선언

  - 위의 예시에서는 예시1이 조상, 예시2가 자손일 때 오버라이딩 가능

 

'Java' 카테고리의 다른 글

연결된 예외  (0) 2022.06.10
사용자 정의 예외 만들기, 예외 되던지기  (0) 2022.05.27
예외의 분류 - 컴파일러 기준  (0) 2022.05.25
예외 발생시키기  (0) 2022.05.25
멀티 catch 블록  (0) 2022.05.24