백엔드/Java

Java 예외 처리

짱뚱짱 2024. 10. 17. 09:00
3.0
-1.0
2.0
java.lang.RuntimeException: num2는 0이 될 수 없습니다.
	at java_project/day06.Exception02.calc(Exception02.java:40)
	at java_project/day06.Exception02.main(Exception02.java:14)
num2는 0이 될 수 없습니다.
-1.0

예외 처리는 코드의 안정성과 신뢰성을 확보하기 위한 필수 요소

 

🔷 RuntimeException : 실행 예외 클래스

  - 대표적인 RuntimeException의 하위 클래스에는 다음과 같은 것들이 있다.

    👉🏻 NullPointerException: null 객체에 접근

    👉🏻 ArrayIndexOutOfBoundsException: 배열의 유효 범위를 초과

    👉🏻 IllegalArgumentException: 메서드에 잘못된 파라미터를 전달

 

public class RuntimeExceptionExample {
    public static void main(String[] args) {
        String str = null;
        // NullPointerException 발생
        System.out.println(str.length());
    }
}

 

 

🔷 Exception : 예외. 개발자가 코드 구현시 발생할 수 있는 에러를 예외
  - 예외처리 : 예외를 개발자가 처리하는 구문
  - 예외가 발생하면 예외 발생 시점부터 코드는 중지 => 예외문구 출력
  - 예외처리 => 예외가 발생할 수 있는 값만을 빼고, 나머지는 정상처리로 유지시키기 위한 기능
  - try ~ catch
  - try ~ catch ~ finally
  - try : 예외가 발생할 가능성이 있는 구문 작성
  - catch : try 구문에서 발생한 예외를 처리
  - finally : try 구문과 상관없이 반드시 처리되어야 하는 구문을 작성 (생략가능)

try {
    System.out.println(1);            // 1을 출력
    System.out.println(2);            // 2를 출력
    System.out.println(1 / 0);        // 여기서 ArithmeticException 발생
} catch (Exception e) {
    e.printStackTrace();              // 예외의 스택 트레이스를 콘솔에 출력
    System.out.println("예외가 발생했습니다~!!"); // 사용자에게 예외 발생 알림
}
System.out.println(4);                // 4 출력
System.out.println(5);                // 5 출력
System.out.println(6);                // 6 출력
System.out.println(7);                // 7 출력

 

결과

1
2
java.lang.ArithmeticException: / by zero
	at java_project/day06.Exception01.main(Exception01.java:22)
예외가 발생했습니다~!!
4
5
6
7

 

 

 

🔷 ArithmeticException : 0으로 나누었을 때 발생하는 Exception

- 예제 : 간단한 계산기. 두 숫자와 연산자를 입력받아 4칙 연산을 수행, 0으로 나누기 같은 예외 상황을 처리

- 만약 연산자가 나누기('/') 또는 나머지('%')이고, 두 번째 숫자가 0이면 RuntimeException을 발생

- 예외처리 : 예외가 발생하면 catch 블록에서 해당 예외의 스택 트레이스와 메시지를 출력. 이로 인해 프로그램은 중단되지 않고, 이후의 코드는 정상 실행

 

public class Exception02 {
    public static void main(String[] args) {
        // ArithmeticException : 0으로 나누었을 때 발생하는 Exception
        Exception02 ex02 = new Exception02();
        try {
            // 예외가 발생할 수 있는 구문 작성
            System.out.println(ex02.calc(1, 2, '+'));  // 3 출력
            System.out.println(ex02.calc(1, 2, '-'));  // -1 출력
            System.out.println(ex02.calc(1, 2, '*'));  // 2 출력
            System.out.println(ex02.calc(1, 0, '/'));  // 예외 발생
        } catch (Exception e) {
            // 예외 처리 작성
            e.printStackTrace();  // 예외의 스택 트레이스를 출력
            System.out.println(e.getMessage());  // 예외 메시지 출력
        }
        System.out.println(ex02.calc(1, 2, '-'));  // -1 출력
    }
}

 

public double calc(int num1, int num2, char op) throws RuntimeException {
    double res = 0;

    // 연산자가 / % 인 경우 num2가 0이면 예외 발생시키기
    if ((op == '/' || op == '%') && num2 == 0) {
        throw new RuntimeException("num2는 0이 될 수 없습니다.");
    }
    switch (op) {
        case '+':
            res = num1 + num2;
            break;
        case '-':
            res = num1 - num2;
            break;
        case '*':
            res = num1 * num2;
            break;
        case '/':
            res = num1 / num2;
            break;
        case '%':
            res = num1 % num2;
            break;
        default:
            // 예외 발생
            throw new RuntimeException(op + "는 산술연산자가 아닙니다.");
    }
    return res;
}

 

 

출력 결과

3.0
-1.0
2.0
java.lang.RuntimeException: num2는 0이 될 수 없습니다.
    at Exception02.calc(Exception02.java:12)
num2는 0이 될 수 없습니다.
-1.0

 

 

🔷 자주 발생하는 예외 코드들

- ArithmeticException : 0으로 나누었을 때 발생
- ArrayIndexOutOfBoundsException :
배열의 index가 범위를 벗어났을 때 발생
- NullPointerException :
객체의 값이 null일 경우, 혹은 객체 자체가 없을 경우
- ClassCastException :
다운 캐스팅이 잘못 되었을 경우

 

i <= arr.length로 설정되어 있어 ArrayIndexOutOfBoundsException이 발생

  - arr.length는 5이므로 유효한 인덱스는 0부터 4까지. i가 5일 때 arr[i]에 접근하면 예외 발생.

// int arr[] = null;
int arr[] = new int[5];
for (int i = 0; i <= arr.length; i++) {
    System.out.println(arr[i]);
}

 

 

🔷 체크 예외와 언체크 예외

  체크 예외(Checked Exception) 언체크 예외(Unchecked Exception)
처리여부 반드시 예외를 처리해야 함 명시적인 처리를 강제하지 않음
확인시점 컴파일 단계 실행단계
예외발생시
트랜잭션 처리
roll-back 하지 않음 roll-back 함
대표 예외 Exception의 상속받는 하위 클래스 중 Runtime Exception을 제외한 모든 예외

* IOException
* SQLException
RuntimeException 하위 예외

* NullPointerException
* IllegalArgumentException
* IndexOutOfBoundException
* SystemException
  • 체크 예외 - 체크 예외는 예외 발생 트랜잭션 처리시 롤백되지 않고, 커밋이 완료된다. 컴파일 시점에 예외를 체크하고, 예외가 발생할 가능성이 있는 경우 반드시 처리해야 한다. 예를 들어, 파일 입출력 관련 예외가 여기에 해당. 
  • 언체크 예외 - 주로 런타임 시 발생. 컴파일 시점에 체크되지 않는다. ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException 등이 여기에 해당. 예외 발생 트랜잭션 처리 시 롤백.

 

🔷 멀티 캐치 구문, 다중 캐치 구문

- 예외를 구체적으로 세분화해서 잡고싶을 때 => 멀티 캐치
- 모든 예외의 최고 조상 : Exception  => 어떤 예외가 발생하든지 다 캐치

try{
}catch(예외클래스명1 객체){
}catch(예외클래스명2 객체){
}
public class ExceptionHandling {
    public static void main(String[] args) {
        int res = 0;

        try {
            // 예외 발생 가능 코드
            // int arr[] = null;
            // arr[1] = 3;
            // int arr1[] = new int[3];
            // arr1[5] = 3;
            res = 1 / 0;
        } catch (NullPointerException e) {
            System.out.println("객체가 null입니다.");
            e.printStackTrace();
        } catch (ArithmeticException e) {
            System.out.println("0으로 나누었습니다.");
            e.printStackTrace();
        } catch (Exception e) {
            // 최고 조상은 가장 마지막에 처리
            e.printStackTrace();
        }

        System.out.println("종료");
    }
}

 

  • NullPointerException: Null 객체 참조
  • ArithmeticException: 0으로 나누었을때
  • Exception: 그 외 모든 예외를 처리.

 

0으로 나누었습니다.
java.lang.ArithmeticException: / by zero
    at ExceptionHandling.main(ExceptionHandling.java:10)
종료

 

🔷 I/O 예외처리

 - 파일 읽기, 쓰기 또는 사용자 입력을 처리할 때 자주 발생. 특히 콘솔에서 입력을 받거나 파일을 다룰 때 IOException이 자주 발생.

package day07;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Exception05 {

	public static void main(String[] args) {
		// I/O Exception 발생 예제
		InputStreamReader isr = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(isr);
		
		String name;
		try {
			//콘솔에서 입력 받아서 그걸 name에서 받아라.
			name = br.readLine();
			System.out.println(name);
			br.close();
			isr.close();
			name = br.readLine();
		} catch(Exception e) {
			e.printStackTrace();
		}

	}

}

InputStreamReaderBufferedReader를 사용하여 콘솔에서 입력된 문자열을 읽고 출력

 

hong
hong
java.io.IOException: Stream closed
	at java.base/java.io.BufferedReader.ensureOpen(BufferedReader.java:122)
	at java.base/java.io.BufferedReader.readLine(BufferedReader.java:319)
	at java.base/java.io.BufferedReader.readLine(BufferedReader.java:392)
	at java_project/day07.Exception05.main(Exception05.java:20)

 

 


"실수는 피할 수 없지만, 그로부터 배우는 것은 우리의 선택이다."

'백엔드 > Java' 카테고리의 다른 글

Java 익명 클래스(Anonymous Class)  (0) 2024.10.20
Java 예외 처리 실습  (1) 2024.10.20
Java 날짜와 시간  (0) 2024.10.16
Java로 고객 관리 시스템 구현  (2) 2024.10.15
객체지향 프로그래밍  (1) 2024.10.14