Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

Java 사용자 정의 예외(Custom Exception) 완벽 가이드

Java에서는 개발자가 직접 예외 클래스를 정의할 수 있으며, 이렇게 만든 예외를 사용자 정의 예외(User-defined Exception) 또는 커스텀 예외(Custom Exception)라고 부릅니다.

사용자 정의 예외를 생성하려면 예외 관련 클래스 중 하나를 상속(extends)해야 합니다. 예외 발생 시 원하는 메시지를 표시하고 싶다면 toString() 메서드를 오버라이드하거나, 슈퍼클래스의 매개변수가 있는 생성자에 String 형태의 메시지를 전달하는 방식을 사용할 수 있습니다.

MyException(String msg){
    super(msg);
}
또는,
public String toString(){
    return " MyException [예외 메시지]";
}

이후 다른 클래스에서 해당 예외를 발생시켜야 하는 지점에서 커스텀 예외 클래스의 객체를 생성하고, throw 키워드를 사용해 예외를 던지면 됩니다.

MyException ex = new MyException();
If(condition……….){
    throw ex;
}

커스텀 체크드 예외와 커스텀 언체크드 예외

  • 모든 예외 클래스는 반드시 Throwable의 하위 클래스여야 합니다.

  • Handle 또는 Declare 규칙(Handle or Declare Rule)에 의해 컴파일러가 자동으로 강제하는 체크드 예외(checked exception)를 작성하려면 Exception 클래스를 상속해야 합니다.

  • 실행 중에 발생하는 런타임 예외(runtime exception)를 작성하려면 RuntimeException 클래스를 상속해야 합니다.

예제: 커스텀 체크드 예외

다음 Java 프로그램은 커스텀 체크드 예외를 생성하고 활용하는 방법을 보여줍니다. 이름이 소문자 알파벳으로만 구성되지 않으면 NotProperNameException을 발생시키는 구조입니다.

import java.util.Scanner;
class NotProperNameException extends Exception {
    NotProperNameException(String msg){
       super(msg);
    }
}
public class CustomCheckedException {
    private String name;
    private int age;
    public static boolean containsAlphabet(String name) {
       for (int i = 0; i < name.length(); i++) {
          char ch = name.charAt(i);
          if (!(ch >= 'a' && ch <= 'z')) {
             return false;
          }
       }
       return true;
    }
    public CustomCheckedException(String name, int age){
       if(!containsAlphabet(name)&&name!=null) {
          String msg = "Improper name (Should contain only characters between a to z (all small))";
          NotProperNameException exName = new NotProperNameException(msg);
          throw exName;
       }
       this.name = name;
       this.age = age;
    }
    public void display(){
       System.out.println("Name of the Student: "+this.name );
       System.out.println("Age of the Student: "+this.age );
    }
    public static void main(String args[]) {
       Scanner sc= new Scanner(System.in);
       System.out.println("Enter the name of the person: ");
       String name = sc.next();
       System.out.println("Enter the age of the person: ");
       int age = sc.nextInt();
       CustomCheckedException obj = new CustomCheckedException(name, age);
       obj.display();
    }
}

컴파일 타임 예외

위 프로그램을 컴파일하면 다음과 같은 오류가 발생합니다. 체크드 예외는 try-catch로 처리하거나 메서드 선언부에 throws로 명시하지 않으면 컴파일 자체가 되지 않습니다.

CustomCheckedException.java:24: error: unreported exception NotProperNameException; must be caught or declared to be thrown
    throw exName;
    ^
1 error

예제: 커스텀 언체크드 예외

커스텀 예외가 상속하는 클래스를 단순히 RuntimeException으로 변경하기만 해도, 해당 예외는 런타임에 발생하는 언체크드 예외가 됩니다.

class NotProperNameException extends RuntimeException {
    NotProperNameException(String msg){
       super(msg);
    }
}

앞선 프로그램에서 NotProperNameException 클래스를 위 코드로 교체한 후 실행하면, 컴파일은 정상적으로 통과되지만 프로그램 실행 도중 다음과 같은 런타임 예외가 발생합니다.

런타임 예외

Enter the name of the person:
Krishna1234
Enter the age of the person:
20
Exception in thread "main" july_set3.NotProperNameException: Improper name (Should contain only characters between a to z (all small))
    at july_set3.CustomCheckedException.<init>(CustomCheckedException.java:25)
    at july_set3.CustomCheckedException.main(CustomCheckedException.java:41)

정리하면, 체크드 예외(Exception 상속)는 컴파일 시점에 처리 여부가 강제되어 안전한 코드 작성에 유리하고, 언체크드 예외(RuntimeException 상속)는 처리를 강제하지 않아 유연하지만 런타임 오류로 이어질 수 있습니다. 상황에 맞게 적절한 부모 클래스를 선택해 커스텀 예외를 설계하는 것이 좋습니다.