43일차 (3) - java (예외 처리)

Yohan·2024년 4월 22일
0

코딩기록

목록 보기
62/156
post-custom-banner

예외 처리 (exception)

예외란?

  • 프로그램을 실행하다 보면 어떤 원인 때문에 비정상적인 동작을 일으키며 프로그램이 종료되는 상황을 본 적이 있을 것이다. 이때 우리는 프로그램이 오류가 발생했다고 말한다.
  • 에러의 종류
    • 우리가 컴파일할때 발생할 수 있는 컴파일 오류
    • 실행 중 발생되는 런타임 오류 가 있다.
  • 컴파일 오류는 개발 툴을 사용하면 빨간 줄을 그어주는 에러이기 때문에 빠르게 파악할 수 있다.
    하지만 런타임 오류는 실행 중에 발생하기 때문에 사전 지식이 없으면 파악하기 힘들다.
  • 자바에서는 런타임 오류를 두 종류로 구분한다. 바로 에러(Error)와 예외(Exception)로 판단한다. 에러는 크게 신경 쓸 필요가 없다. 코드로 막을 수 없기 때문이다. 우리가 처리하고자 하는 것은 바로 예외이다. 예외는 프로그래머가 직접 예측하여 예방할 수 있는 처리 가능한 오류를 말한다.

예외 처리란?

에러를 직접 해결하는 것이 아니다. 프로그램에 문제가 될 만한 부분을 예상하여 사전에 “문제가 발생하면 이렇게 처리하라!” 라고 프로그래밍 하는 것을 예외 처리라고 한다.

대표적인 실행 예외의 종류

  1. NullPointerException
  • 객체 참조가 없는 상태, 즉 null 값을 갖는 참조 변수로 객체 접근 연산자인 dot(.)를 사용했을 때 발생
  1. ArrayIndexOutOfBoundsException
  • 배열에서 인덱스 범위를 초과하여 사용할 경우 발생합니다.
  1. NumberFormatException
  • 문자열로 되어 있는 데이터를 숫자로 변경하는 경우에 발생
  1. ClassCastException
  • 형 변환은 부모 클래스와 자식 클래스간에 발생하고 구현 클래스와 인터페이스 간에도 발생합니다. 상속 또는 구현 관계가 아니라면 다른 클래스로 타입을 변환할 수 없다.

예외 처리 문법

try catch 구문

  • try 블록에는 예외 발생 가능성이 있는 코드를 작성 , try 블록의 코드가 예외 발생 없이 정상 실행되면 catch 블록은 실행되지 않는다.
  • try 내부에서 예외가 발생하면 즉시 실행을 멈추고 catch 블록으로 이동하여 예외 처리 코드를 실행 한다.
  • 아래와 같이 작성
    public static void main(String[] args) {

        int n1 = 10, n2 = 0;

        System.out.println("나눗셈 시작!");

        try {
            int result = n1 / n2; // 예외 발생 가능성이 있는 코드
        } catch(Exception e) {
            // 예외가 발생했을 경우 프로그래밍이 튕기는 대신 실행할 코드
            System.out.println("0으로 나누면 안됩니다~");
        }

        System.out.println("나눗셈 정상 종료!");
    }

다중 catch와 Multi catch

  • 하나의 try 블록 내부에는 다양한 종류의 예외가 발생할 수 있다.
    그 때 예외의 종류마다 처리를 다르게 하고 싶다면 다중 catch 블록을 작성하여 처리할 수 있다.


public class TryExample2 {

    /*
                 Object
                    |
                Throwable
                /       \
             Error     Exception (예외 정보를 가지고 있는 객체)


     */

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

        try {
            System.out.print("정수1: ");
            int n1 = Integer.parseInt(sc.next()); // NumberFormatException

            System.out.print("정수2: ");
            int n2 = sc.nextInt(); // InputMismatchException

            int result = n1 / n2; // ArithmeticException
            System.out.println("result = " + result);
            
        } catch (InputMismatchException e) {
            System.out.println("정수를 입력하시라니까요~?");
        } catch (NumberFormatException e) {
            System.out.println("문자로 변환할 수 없는 숫자입니다.");
        } catch (ArithmeticException e) {
            System.out.println("0으로 나눌 수 없습니다.");
            e.printStackTrace(); // 에러 로그를 띄움 - 개발시에 유용
        } catch (Exception e) { // 기타 등등의 에러 처리
            System.out.println("알 수 없는 에러입니다.");
        }


        System.out.println("프로그램 정상 종료!");
    }
}
  • e.printStackTrace(); 를 통해 에러 로그를 띄울 수 있다.
  • 예외의 종류마다 처리를 다르게 하고 마지막에 Exception을 통해 나머지 에러를 처리할 수 있다.

예외 떠넘기기 (throws)

  • 생길 수 있는 예외를 명시해주는 역할. catch는 사용자 마음대로 코드를 설정할 수 있도록 한다. (예외를 떠넘김)
  • 반드시 실행 메서드에서 try ~ catch 구문을 통해 예외처리를 해서 사용해야 한다. (반드시 호출부에서 예외 처리가 강요됨)
    // 문자열을 정수로 변환하는 메서드
    public int convert(String str) throws NumberFormatException {

        int n = Integer.parseInt(str);
        return n;
    }
  • 위 예시를 보면 throws에는 covert 메서드를 실행할 때 NumberFormatException 예외가 생길 수 있으니 조심하고 반드시 try ~ catch 구문을 만들어서 예외 처리를 해서 사용해 라는 말을 내포하고 있다.

예외를 강제로 발생시키는 throw


public class LoginUser {

    private String account; // 가입시 계정명
    private String password; // 가입시 패스워드

    public LoginUser(String account, String password) {
        this.account = account;
        this.password = password;
    }

    public enum LoginStatus {
        SUCCESS, ID_FAIL, PW_FAIL
    }

    // 로그인 검증
    public LoginStatus loginValidate(String inputAccount, String inputPassword) throws InvalidLoginInputException {
        // 아이디가 일치하는가?
        if (!inputAccount.equals(account)) {
            // 상수를 return 하는 것 보다 시스템적으로 훨씬 더 강력하게 알림
            // return LoginStatus.ID_FAIL;
            throw new InvalidLoginInputException("계정이 일치하지 않습니다.");
        }

        // 비번이 일치하는가?
        if (!inputPassword.equals(password)) {
        	// return LoginStatus.PW_FAIL;
            throw new InvalidLoginInputException("비밀번호가 일치하지 않습니다.");
        }

        System.out.println("로그인이 성공했습니다.");
        // return LoginStatus.SUCCESS;
    }
}
  • 위 예시에서 계정과 비밀번호가 일치하지 않았을 때 실패에 대한 상수를 return할 수 있다. 하지만 이렇게 처리하게되면 실제로 계정과 비밀번호가 일치하지 않았을 때의 심각성을 줄 수 없다.
  • 그렇기 때문에 이러한 경우에 throw를 통해 예외를 강제로 발생시킨다.
  • 예상되는 예외를 throws에 입력해주고 throw new 를 통해 예외를 발생시킨다.

사용자 정의 예외

package day10.exception;

public class InvalidLoginInputException extends Exception {

    public InvalidLoginInputException() {
    }

    public InvalidLoginInputException(String message) {
        super(message);
    }
}
  • 단, 위 예시에 적용한 예외처럼 일치하는 예외처리 문법이 없다면 직접 사용자가 정의해서 만들어서 사용할 수 있다.
profile
백엔드 개발자
post-custom-banner

0개의 댓글