[Java] 예외(Exception) 처리

지니·2025년 3월 3일

JAVA

목록 보기
5/9
post-thumbnail

1. 오류(error)의 종류


  • 컴파일 에러 : 컴파일시에 발생하는 에러로 문법적인 오류라고 생각하면 된다.
  • 런타임 에러 : 실행시에 발생하는 에러
  • 논리적 에러 : 실행은 되지만 의도와 다르게 동작하는 것

2. 예외 처리


2-1. 오류와 예외

오류(error)예외(exception) 모두 시스템 상에서 프로그램에 문제가 발생해 실행중인 프로그램이 종료되는 것이다.

에러(error)는 예측해서 처리하는게 불가능하고 예외(exception)는 예측해서 처리하는게 가능하다.

2-1. 예외 처리를 사용하는 이유

  • 미리 예측하고 컨트롤 할 수 있는 예외를 처리해 코드의 안전성과 신뢰성을 높일 수 있다.
  • 예외가 발생한 원인과 위치를 쉽게 파악할 수 있다.

3. 예외 클래스의 종류


3-1. 예외 클래스의 계층 구조

  • 오류와 예외는 모두 Throwable의 자식 클래스
  • Unchecked Exception 기본적으로 이미 처리 되어 있고 실행 중인 프로그램이 종료되게 작성
    • Runtime Exception은 런타임 시점에 해당 예외 클래스 타입의 Exception이 발생
  • Checked Exception은 반드시 예외 처리를 해줘야 하는 예외
    • 예외처리를 하지 않은 경우엔 컴파일 에러가 발생한다.

3-2. RuntimeException의 자식 클래스

클래스명발생 상황
ArithmeticException0으로 나누는 경우 발생
ArrayIndexOutOfBoundsException배열의 index 범위를 넘어서 참조하는 경우 발생
NullPointerException객체가 참조되지 않는 상태(Null)로 객체에 접근하는 경우 발생
ClassCastException형 변환 시 문제가 있을 경우 발생
NegativeArraySizeException배열의 크기를 음수로 지정한 경우 발생

4. 예외 던지기


4-1. throw와 throws

throw
: 개발자가 자신의 의도와 다른 경우 고의로 예외를 발생시키는 것으로 컴파일 문제는 발생하지 않음

throws
: 메소드 내에서 예외처리를 하지 않고 해당 메소드를 사용한 곳에서 예외 처리를 하도록 전달하는 것

4-2. 실제 코드

  • 가지고 있는 돈이 가격보다 적으면 상품을 구매할 수 없으므로 throw를 통해 예외 발생시키기
  • throws를 통해 예외를 메소드를 호출하는 메소드에게 전달하기
  • 메소드가 호출되는 main 메소드 안에서 예외 처리를 해주고 있다.

⁉️ main에서 throws를 하면 어떻게 될까?
위에서 'throws'를 통해 예외를 메소드를 호출한다고 했다. 그렇다면 가장 마지막에 있는 main 메소드에서 thorws 처리를 하면 어떻게 될까? 이 경우에서는 JVM에서 예외 처리를 해 예외 내용을 console에 출력한다.
참고로 main 메소드에서 throws Exception을 붙이는 것은 좋지 않은 방법이니 지양하는 것이 좋다.

/* 1. Test.java */
public class Test {
    // 메서드가 예외 처리를 직접 하지 않고 호출한 쪽으로 예외를 전달
    public void checkEnoughMoney(int price, int money) throws Exception {
        if (money >= price) {
            System.out.println("상품을 구매할 수 있습니다.");
        } else {
            // 예외를 발생시켜 호출한 쪽에서 처리하도록 함
            throw new Exception();
        }
    }
}

/* 2. Application.java */
public class Application {
    public static void main(String[] args) {
        Test test = new Test();

        // 호출한 쪽에서 전달받은 예외를 처리
        try {
            test.checkEnoughMoney(10000, 50000);
            test.checkEnoughMoney(60000, 50000);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5. 예외 처리


5-1. try-catch(또는 try-catch-finally)

발생한 Exception을 직접 처리하는 방법

  • try 블럭
    • 예외 발생 가능성이 있는 코드를 포함하여 작성
  • catch 블럭
    • 예외 타입에 대한 처리를 기술하는 블럭
    • 여러 개의 catch 블럭 사용이 가능하고 상위 타입의 예외 처리 블럭이 더 아래쪽에 위치해야 한다.
  • finally 블럭
    • 예외 발생과 상관 없이 꼭 실행되어야 하는 코드를 작성하는 부분
    • 주로 java.io나 java.sql패키지의 메소드 처리 시 자원 반납을 위해 사용
import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int a = sc.nextInt();
        int b = sc.nextInt();

        try{
		        // ArithmeticException 예외가 발생할 수 있는 부분 (b가 0일수도)
            int result = a/b; 
            System.out.println(result);
        }catch(ArithmeticException e){
		        // 예외가 발생했을 때 실행하고자 하는 부분
            System.out.println("0으로는 나눌 수 없습니다.");
            // 어떤 예외가 발생했는지 알려주는 메소
            e.printStackTrace();
        }finally { 
		        // 예외 발생 여부에 상관 없이 무조건 실행하는 부분
            System.out.println("입력한 숫자 : " + a + " , " + b);
        }
    }
}

5-2. try-with-resource

입출력에서 사용되는 스트림의 자원 반납을 finally 블럭을 사용하지 않고 용이하게 처리하기 위해 자바 7버전부터 추가된 문법

public class Test{
    public static void main(String[] args) {
        /* 자원을 반납 해야 하는 인스턴스를 try 옆 소괄호에서 생성하면
        * 해당 블럭 종료 시 자동 close 작업이 일어난다. */
        try (BufferedReader in = new BufferedReader(new FileReader("test.dat"));){
            String s;

            while((s = in.readLine()) != null){
                System.out.println(s);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

0개의 댓글