Java의 예외 처리 (Exception Handling)



예외 처리(Exception Handling)는 프로그램이 비정상적으로 종료되지 않도록 하는 방법입니다.

1. 예외의 종류

  • 일반 예외 (Checked Exception)
    • 컴파일러가 예외 처리 코드를 요구하는 예외입니다.
    • 예외 처리가 되어 있지 않으면 컴파일 에러가 발생합니다.
    • IOException, SQLException 등
  • 실행 예외 (Unchecked Exception)
    • 컴파일러가 예외 처리 코드를 요구하지 않는 예외입니다.
    • 런타임 시에 발생하며, 프로그램 실행 중 예외를 처리할 수 있습니다.
    • NullPointerException, ArrayIndexOutOfBoundsException, ArithmeticException 등


2. 예외 처리 기본 구조

  • try-catch-finally 블록을 사용하여 예외를 처리합니다.
try {
    // 예외가 발생할 가능성이 있는 코드
} catch (Exception e) {
    // 예외가 발생했을 때 처리할 코드
} finally {
    // 예외 발생 여부와 상관없이 항상 실행되는 코드 (선택 사항)
}

1) try 블록

  • try 블록 안에는 예외가 발생할 가능성이 있는 코드를 작성합니다.
  • 예외가 발생하면, 즉시 catch 블록으로 넘어가 예외를 처리합니다.

2) catch 블록

  • catch 블록에서는 발생한 예외에 대한 처리 코드를 작성합니다.
  • 여러 개의 예외를 다중 catch 블록으로 처리할 수 있으며, 구체적인 예외부터 처리하는 것이 좋습니다.

3) finally 블록

  • finally 블록은 예외 발생 여부와 관계없이 실행됩니다. 주로 리소스 해제와 같은 작업을 수행합니다.


3. 예외 처리 종류

1) ArithmeticException 처리 (산술 연산 예외 처리)

  • 산술 연산 예외가 발생하는 상황입니다. 예를 들어, 0으로 나누기를 시도하면 ArithmeticException이 발생합니다
public static String divide(int x, int y) {
    return x + " / " + y + " = " + (x / y);
}

try {
    System.out.println(divide(6, 0));
} catch (ArithmeticException e) {
    System.out.println("나누기 연산 중 에러 발생 >> " + e.getMessage());
} finally {
    System.out.println("연산 종료");
}

출력 결과

나누기 연산 중 에러 발생 >> / by zero
연산 종료


2) NullPointerException 처리

  • null 값을 참조하려고 시도하면 NullPointerException이 발생합니다.
public static int getLength(String str) {
    return str.length(); // // str이 null일 경우 NullPointerException 발생
}

try {
    System.out.println("단어 길이: " + getLength(null));
} catch (NullPointerException e) {
    System.out.println("단어 길이 연산 중 에러 발생 >> " + e.getMessage());
}

출력 결과

단어 길이 연산 중 에러 발생 >> null


3) ArrayIndexOutOfBoundsException 처리

  • 배열의 잘못된 인덱스에 접근하려고 시도하면 ArrayIndexOutOfBoundsException이 발생합니다.
int[] numbers = {10, 20, 30, 40, 50};

try {
    System.out.println(numbers[5]);  // 배열 범위를 벗어난 인덱스 접근
} catch (ArrayIndexOutOfBoundsException e) {
    System.out.println("배열 인덱스 초과 >> " + e.getMessage());
}

출력 결과

배열 인덱스 초과 >> Index 5 out of bounds for length 5


4) InputMismatchException 처리 (사용자 입력 예외 처리)

  • 사용자가 잘못된 형식을 입력하면 InputMismatchException이 발생합니다.
Scanner sc = new Scanner(System.in);
try {
    System.out.print("정수를 입력해주세요 >> ");
    int number = sc.nextInt(); // // 정수가 아닌 값 입력 시 예외 발생
    System.out.println("입력한 정수는 >> " + number);
} catch (InputMismatchException e) {
    System.out.println("정수를 입력하지 않았습니다. >> " + e.getMessage());
} finally {
    sc.close();
}

출력 결과 (문자 입력 시)

정수를 입력하지 않았습니다. >> null


4. 다중 예외 처리 (Multiple Catch)

다양한 예외를 한 번에 처리할 수 있는 다중 catch 블록입니다.

Scanner sc = null;
try {
    sc = new Scanner(System.in);
    System.out.print("숫자를 입력하세요 >> ");
    String input = sc.nextLine();
    int number = Integer.parseInt(input);  // NumberFormatException
    int result = 100 / number;  // ArithmeticException
    int[] array = new int[5];
    array[number] = 10;  // ArrayIndexOutOfBoundsException
    System.out.println("결과 >> " + Arrays.toString(array));
} catch (NumberFormatException e) {
    System.out.println("숫자 형식이 잘못되었습니다. >> " + e.getMessage());
} catch (ArithmeticException e) {
    System.out.println("0으로 나눌 수 없습니다. >> " + e.getMessage());
} catch (ArrayIndexOutOfBoundsException e) {
    System.out.println("배열 인덱스 범위를 초과했습니다. >> " + e.getMessage());
} catch (Exception e) {
    // General exception handler (Exception e)
    // 예상치 못한 예외나 명시적으로 처리하지 않은 예외를 잡는 "마지막 방어선"
    // - 일반적으로 마지막 catch 블록으로 사용되며, 더 구체적인 예외들은 해당 블록 앞에 위치해야 함
    System.out.println("알 수 없는 예외가 발생했습니다. >> " + e.getMessage());
} finally {
    if (sc != null) {
        sc.close();
    }
}

출력 결과

  • 입력이 “0”일 경우
    0으로 나눌 수 없습니다. >> / by zero
    
  • 입력이 “abc”일 경우
    숫자 형식이 잘못되었습니다. >> For input string: "abc"
    


5. NumberFormatException 과 InputMismatchException 차이점

  • NumberFormatException 은 문자열을 숫자로 변환하는 과정에서 형식이 맞지 않으면 발생하는 예외입니다.
  • "a"Integer.parseInt()로 숫자로 변환하려고 시도할 때 발생합니다.

    String input = "a";
    int number = Integer.parseInt(input);  // NumberFormatException 발생
    
  • InputMismatchException 은 Scanner로 입력을 받을 때, 예상한 타입과 다른 입력이 들어오면 발생합니다.
  • nextInt()로 숫자를 기대하는데 문자열 "a"가 입력되면 발생합니다.

    Scanner sc = new Scanner(System.in);
    int number = sc.nextInt();  // InputMismatchException 발생
    
  • NumberFormatException은 문자열 변환 오류에 대한 예외이며,
  • InputMismatchException은 Scanner로 잘못된 타입의 입력을 처리할 때 발생합니다.


6. 예외 처리의 장점

  • 예외가 발생하더라도, 처리함으로써 프로그램이 종료되지 않고 안정적으로 실행됩니다.
  • 예외를 처리하는 과정에서 오류의 원인을 파악할 수 있으며, 정보를 활용하여 디버깅할 수 있습니다.
  • 프로그램의 안정성을 유지할 수 있습니다.