Programming Language/Java

[Java] 14. 예외 처리(Exception handling)(3) - 메서드에 예외 선언하기

lumana 2024. 7. 9. 05:38

예외 처리(3) - 메서드에 예외 선언하기

메서드에 예외 선언하기

  • 지금까지 다룬 try-catch 사용법 말고 예외를 메서드에 선언하는 방법이 있다.

  • 메서드 선언부에 키워드 throws를 사용해서 메서드 내에서 발생할 수 있는 예외를 적어주기만 하면 된다.

    • 예외가 여러 개일 경우 쉼표(,)로 구분한다
void method() throws Exception1, Exception2, ... ExceptionN {
     // method body
}
  • Exception 클래스를 메서드에 선언하면, 모든 종류의 예외가 발생할 가능성이 있다는 뜻이다.

  • 메서드의 선언부에 예외를 선언하므로써 메서드를 사용하려는 사람이 메서드를 사용하기 위해 어떠한 예외들이 처리되어져야 하는지를 쉽게 할 수 있다.

    • 기존의 많은 언어들은 메서드에 예외선언을 하지 않는다.

      • 자바에서는 메서드 내에서 발생할 가능성이 있는 예외를 선언부에 명시해 이 메서드를 사용하는 쪽에서는 이에 대한 처리를 하도록 강요하여 견고한 프로그램 코드를 작성하도록 돕는다.
  • 메서드에 예외를 선언할 때 일반적으로 RuntimeException 클래스들은 적지 않는다.

    • 보통 반드시 처리해주어야 하는 예외들만 선언한다

  • 사실 예외를 메서드의 throws에 명시하는 것은 예외를 처리하는 것이 아니라, 자신(예외가 발생할 가능성이 있는 메서드)를 호출한 메서드에게 예외를 전달하여 예외처리를 떠맡기는 것이다.

  • 예외를 전달받은 메서드가 또다시 자신을 호출한 메서드에게 전달할 수 있으며, 이런 식으로 계속 Call Stack에 있는 메서드를 따라 전달되다 마지막에 메인 메서드에서도 예외처리가 되지 않으면 main메서드 마저 종료되어 프로그램 전체가 종료된다

    • 예외를 전달하는 것만으로 예외가 처리된 것이 아니다

      • 결국 어느 한 곳에서는 반드시 try-catch문으로 예외처리를 해주어야 한다

Example) 메서드 내 예외처리 vs 예외 전달

method1()에서 예외 처리

class ExceptionEx13 {
    public static void main(String[] args) {
        method1();    // 같은 클래스 내의 static멤버이므로 객체 생성없이 직접 호출 가능
    }    // main메서드의 끝

    static void method1() {
        try {
            throw new Exception();
        } catch (Exception e) {
            System.out.println("method1메서드에서 예외가 처리되었습니다.");
            e.printStackTrace();
        }
    }    // method1의 끝
}

예외를 전달하여 예외처리

class ExceptionEx14 {
    public static void main(String[] args) {
        try {
            method1();
        } catch (Exception e) {
            System.out.println("main메서드에서예외가 처리되었습니다.");
            e.printStackTrace();
        }
    }    // main메서드의 끝

    static void method1() throws Exception {
        throw new Exception();
    }    // method1()의 끝
}    // class의 끝
  • ExceptionEx13처럼 예외가 발생한 메서드 내에서 처리되어지면 호추한 메서드에서는 예외가 발생했다는 사실조차 모르게 된다.

  • 이처럼 예외가 발생한 메서드에서 예외를 처리할 수도 있고, 예외가 발생한 메서드를 호출한 메서드에서 처리할 수도 있다.

    • 또는 두 메서드가 예외처리를 분담할 수도 있다.

Example 8.16

import java.io.*;

class ExceptionEx16 {
    public static void main(String[] args) {
        try {
            File f = createFile(args[0]);
            System.out.println(f.getName() + " 파일이 성공적으로 생성되었습니다.");
        } catch (Exception e) {
            System.out.println(e.getMessage() + " 다시 입력해주시기 바랍니다.");
        }
    }    // main메서드의 끝

    static File createFile(String fileName) throws Exception {
        if (fileName==null || fileName.equals(""))
            throw new Exception("파일이름이 유효하지 않습니다.");
        File f = new File(fileName);    // File클래스의 객체를 만든다.
        // File객체의 createNewFile메서드를 이용해서 실제 파일을 생성한다.
        f.createNewFile();
        return f;    // 생성된 객체의 참조를 반환한다.
    }    // createFile메서드의 끝
}    // class의 끝
  • 메서드 내에서 자체적으로 처리해도 되는 것은 메서드 내에서 try-catch문을 사용해서 처리하자

  • 위 예제처럼 메서드에 호출 시 넘겨받아야 할 값(fileName)을 다시 받아야 하는 경우(즉, 메서드 내에서 자체적으로 해결이 안 되는 경우)에는 예외를 메서드에 선언해서 호출한 메서드에서 처리해야 한다.

참조) Java의 정석 3rd edition(남궁성, 도우출판)