zkvn99

[Java] Exception Handling 본문

Language/Java

[Java] Exception Handling

zkvn1103 2023. 8. 1. 00:56

Exception

예외란? (Exception)

프로그램 실행 중 즉, 런타임에 발생하는 문제로 예외 처리를 통해 대응할 수 있다.

 

오류란? (Error)

오류는 프로그램 실행 중 심각한 문제가 발생하여 복구할 수 없는 상태를 말한다

더보기

오류의 종류로는 메모리 부족, 메모리 누수, 스택 오버플로우, 라이브러리 비호환성, 무한 재귀

대표적인 오류로는 OutofMemoryError, StackOverflowError 등이 있다

 

오류(Error)와 예외(Exception)는 둘 다 프로그램 실행 중에 발생하는 문제이지만,

오류는 일반적으로 복구가 불가능하며, 프로그램이 종료되고

예외는 예외 처리를 통해 복구가 가능하며, 프로그램의 정상적인 실행은 유지할 수 있다.

 

예외 처리에 들어가기 전, 예외 계층에 대해서 살펴보자면

 

예외 계층

예외 계층 구조 / 출처 : https://www.geeksforgeeks.org/exceptions-in-java/

모든 예외 및 오류 유형은 계층 구조의 기본 클래스인 Throwable 클래스의 하위 클래스이다.

 

Throwable

모든 예외 클래스의 최상위 클래스이며, 직접 객체를 생성하여 사용하지는 않는다.

 

Exception

개발자가 직접 처리해야 하는 예외들을 나타낸다.

 

Error

개발자가 직접 처리하지 않으며, 주로 시스템 레벨에서 처리된다.

 

Unchecked Exception

프로그래밍 실수에 의해 발생하는 예외들, 개발자가 예외 처리를 강제되지 않음 

 

Checked Exception

외부 리소스와의 상호작용이나 입출력 등에서 발생하는 예외들, 개발자가 반드시 예외 처리를 명시적으로 해야 함

 

그렇다면, 이제 예외 처리를 위한 예외 유형에 대해서 정리하자면

예외 유형

예외 유형 구조 / 출처 : https://www.geeksforgeeks.org/exceptions-in-java/

Built-in Exception

Java 표준 라이브러리에 포함되어 있는 예외로 Checked, Unchecked로 나뉜다.

 

Checked의 경우는 컴파일 할 때 컴파일러에 의해 확인되며 

주로 외부 리소스와 상호작용(파일, 네트워크 연결)이나 데이터베이스 연결 등에서 발생하는 예외

import java.io.*;

public class FileProcessor {
    public void readFile(String fileName) throws FileNotFoundException, IOException {
        try (FileInputStream fis = new FileInputStream(fileName)) {
            // 파일 읽기 작업 수행
        } catch (FileNotFoundException e) {
            // 파일이 없는 경우 처리
            throw e;
        } catch (IOException e) {
            // 파일 읽기 예외 처리
            throw e;
        }
    }
}
// FileNotFoundException, IOException가 Checked Exception
// 메서드 선언부에 throw 를 통해 예외 선언

Unchecked의 경우 컴파일 할 때 확인하지 않으며,

프로그램이 예외를 발생시켜도, 컴파일 오류를 발생시키지 않음

public class ArrayExample {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3};
        try {
            // 인덱스 범위를 벗어나는 값에 접근하려고 하면 예외 발생
            int value = arr[3]; // 인덱스 범위는 0부터 2까지이므로 3은 유효하지 않음
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("배열 인덱스를 벗어남");
        }
    }
}
// ArrayIndexOutOfBoundsException가 Unchecked Exception
// 예외 발생 시 처리를 강제하지 않음

 

User-Defined Exception

개발자가 직접 예외 클래스를 정의하여 생성하는 예외로 사용자 정의 예외라고 한다

// 사용자 정의 예외 클래스를 정의합니다.
class CustomException extends Exception {
    // 생성자를 이용하여 예외 메시지를 전달받습니다.
    public CustomException(String message) {
        // 부모 클래스의 생성자를 호출하여 예외 메시지를 설정합니다.
        super(message);
    }
}

public class CustomExceptionExample {
    // 사용자 정의 예외를 발생시키는 메서드를 작성합니다.
    public void throwCustomException() throws CustomException {
        // 특정 상황에서 사용자 정의 예외를 발생시킵니다.
        throw new CustomException("사용자 정의 예외 발생!");
    }

    public static void main(String[] args) {
        CustomExceptionExample example = new CustomExceptionExample();
        try {
            // 메서드 호출 시 사용자 정의 예외가 발생하므로 예외 처리를 수행합니다.
            example.throwCustomException();
        } catch (CustomException e) {
            // 사용자 정의 예외를 잡아서 처리합니다.
            System.out.println("예외 메시지: " + e.getMessage()); // "사용자 정의 예외 발생!"이 출력됨
        }
    }
}

 

위와 같은 예외 정보를 받아오는 방법도 있다.

 

printStackTrace() : 예외가 발생한 경로와 메서드 호출 흐름을 보여줌

public static void main(String[] args) {
    try {
        int result = 10 / 0; // ArithmeticException 발생
    } catch (ArithmeticException e) {
        // 예외 정보를 출력
        e.printStackTrace();
    }
}
// java.lang.ArithmeticException: / by zero
//   at Main.main(Main.java:4)

getMessage() : 예외 객체의 메시지만을 문자열 형태로 반환

public class NullPointerExceptionExample {
    public static void main(String[] args) {
        try {
            String str = null;
            int length = str.length(); // NullPointerException 발생
        } catch (NullPointerException e) {
            // 예외 메시지를 출력
            System.out.println("예외 메시지: " + e.getMessage());
        }
    }
}

// 예외 메시지: null

toString() : 예외 객체의 문자열 표현을 반환, getClass().getName() + getMessage() 

public static void main(String[] args) {
    try {
        String str = null;
        int length = str.length(); // NullPointerException 발생
    } catch (NullPointerException e) {
        // 예외 객체의 문자열 표현을 출력
        System.out.println(e.toString());
    }
}

// java.lang.NullPointerException

그렇다면 이제 예외 처리 방법에 대해 알아보자면

Exception Handling

Java 예외 처리는 5개의 키워드(try-catch, throw, throws, finally) 통해 관리된다

 

try-catch : 예외를 처리하는 기본적인 구조 try 블록 안에 예외 발생 코드, catch에 예외 처리 코드

public static void main(String[] args) {
    try {
        int result = 10 / 0; // ArithmeticException 발생
    } catch (ArithmeticException e) {
        // 예외를 처리하는 코드 작성
        System.out.println("0으로 나눌 수 없습니다.");
    }
}

 

throw : 개발자가 직접 예외를 발생, 메서드 내에서 특정 조건이 만족되지 않거나 오류 상태일 때 사용

void someMethod(int value) {
    if (value < 0) {
        throw new IllegalArgumentException("value는 0 이상이어야 합니다.");
    }
    // 메서드 로직 계속 실행
}

throws : 해당 메서드가 던질 수 있는 예외를 명시(선언된 메서드는 예외 처리 x), 호출한 쪽으로 예외 처리 책임 전가

public void readFile(String fileName) throws FileNotFoundException, IOException {
    // 파일 읽기 작업 수행
}

 

finally : try-catch 문의 일부로, 예외 발생 여부와 상관없이 항상 실행되는 블록

public static void main(String[] args) {
    try {
        int result = 10 / 0; // ArithmeticException 발생
    } catch (ArithmeticException e) {
        // 예외를 처리하는 코드 작성
        System.out.println("0으로 나눌 수 없습니다.");
    } finally {
        // 항상 실행되어야 하는 코드 작성
        System.out.println("예외 처리 완료");
    }
}

그렇다면 이런 예외가 발생했을 때 어떻게 아느냐? 하면 JVM이 해당 예외를 프로그램에 전달하는 역할

 

JVM 예외 전달 과정

  1. 예외 발생 : 프로그램이 실행 중 문제가 발생하면 예외가 발생 (이 예외는 프로그램이 예외를 일으킨 지점에서 생성)
  2. 예외 객체 생성 : JVM은 해당 예외를 표현하는 예외 객체를 생성(타입과 정보를 담음)
  3. 호출 스택 역추적 : 예외 발생 지점을 찾고, 정보를 예외 객체에 추가(발생 경로를 추적)
  4. 예외 전달 : 역추적하여 예외 정보를 예왜 객체에 담은 후, 프로그램으로 전달 (예외 던지기)

호출 스택

프로그램이 실행되면서 메서드 호출이 발생할 때 해당 호출들의 순서와 메서드들이 실행되는 공간을 기록하는 자료구조

더보기

작동 원리

  1. 메서드 호출 : 프로그램이 실행되면서 메서드가 호출되면 해당 메서드의 실행에 필요한 정보(매개변수 등) 스택에 기록
  2. 스택 프레임 : 메서드 호출에 따라 메서드의 정보가 스택 프레임 형태로 쌓임 (매개변수, 지역 변수, 복귀 주소 등의 정보)
  3. 메서드 실행 : 호출된 메서드는 해당 메서드의 코드를 실행하고, 필요한 작업 수행
  4. 메서드 반환 : 메서드 실행이 완료되면 해당 메서드는 호출 스택에서 제거, 반환 주소를 참조하여 이전 스택 프레임으로 복귀

이렇게 호출 스택에 쌓인 프레임들이 차례로 제거되면서 메서드의 실행 흐름이 이어짐, 다른 메서드가 호출되면 호출 스택에 새로운 스택 프레임이 추가됨

 

kamranahmedse의 자바 로드맵을 기반으로한 학습입니다

https://github.com/kamranahmedse/developer-roadmap

 

GitHub - kamranahmedse/developer-roadmap: Interactive roadmaps, guides and other educational content to help developers grow in

Interactive roadmaps, guides and other educational content to help developers grow in their careers. - GitHub - kamranahmedse/developer-roadmap: Interactive roadmaps, guides and other educational c...

github.com

 

* 참고 자료

https://www.geeksforgeeks.org/exceptions-in-java/

 

Exceptions in Java - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org

 

'Language > Java' 카테고리의 다른 글

[Spring] 데이터 전달  (0) 2023.09.16
[Java] Basic Syntax  (0) 2023.07.30
[Java] 코딩테스트 자주 쓰는 메서드  (0) 2023.06.27
[Java] Array & Collection  (0) 2023.05.27
[Java] int 배열 vs Integer 배열  (0) 2023.05.26