Exception

.·2022년 7월 28일
0

Computer Science

목록 보기
45/81

Exception vs Error

Exception 예외

  • 정상적인 프로그램의 흐름을 어긋나는 것
  • 입력 값에 대한 처리가 불가능하거나, 프로그램 실행 중 참조값이 잘못된 경우 등
  • 자바의 예외는 개발자가 예외 상황을 미리 예측하여 코드에서 직접 처리할 수 있다.

Error 에러

  • 시스템에 비정상적인 상황이 발생한 경우
  • 주로 자바 가상 머신에서 발생시킴
  • 어플리케이션 코드에서 잡을 수 없다.
  • ex> OutOfMemoryError, ThreadDeath, StackOverflowError, ..

checked vs unchecked exception

  1. Checked Exception
    • RuntimeException을 상속하지 않는다.
    • 예외를 꼭 처리해야 한다.
  2. Unchecked Exception
    • RuntimeException을 상속한다.
    • 명시적으로 처리하지 않아도 된다.

Checked Exception

컴파일 타임에 확인할 수 있는 예외

  • Throwable 하위 클래스 중 RuntimeException을 상속하지 않는 클래스들은 checked exception이다.
  • 메서드 내의 어떤 코드가 checked exception을 발생시키면, 메서드는 예외를 처리하거나 throws 키워드를 사용하여 예외를 구체화해야 한다.

종류

1. fully checked exception

  • chekced exception의 모든 자식 클래스들 또한 checked인 경우
  • ex> IOException, InterruptedException

2. partially checked exception

  • checked exception의 자식 클래스들 중 unchecked도 있는 경우
  • ex> Exception

예시

“C:\test\a.txt” 위치의 파일을 열고 첫 3문장을 출력하는 자바 프로그램

import java.io.*;

class Application {

    public static void main(String[] args) throws IOException {
        FileReader file = new FIleReader("C:\\test\\a.text");
        BufferedREader fileInput = new BufferedREader(file);

        for (int counter = 0; counter < 3; counter++;) {
            System.out.println(fileInput.readLine());
        }

        fileInput.close();
    }
}
  • 이 프로그램은 main()에서 chekced exception을 throw하기 때문에 컴파일하지 않는다.
  • checked exception
    • readLine(), close() : IOException
    • FileReader(): FileNotFoundException → IOException의 subclass

Unchecked Exception

컴파일 타임에 확인되지 않는 예외

  • ErrorRuntimeException 클래스 하위 예외들은 unchecked exception이다.

예시

컴파일은 잘 되지만 실행(run) 시에 ArithmeticException 발생

class Application {
    public static void main(String[] args) {
        int x = 0;
        int y = 10;
        int z = y / x;  // divided by 0, mathematically incorrect
    }
}

예외 처리

throw vs throws

throw

프로그래머가 예외를 강제적으로 발생시키는 방법

throw new SomeException();
  • 코드에 작성

throws

호출한 쪽에 예외 처리를 전가하는 방법

public class Application {
    public static void main(String[] args) {
        Calculator calculator = new Calculator();
        try {
            calculator.add("1", "ㄱ");
        catch (NumberFormatException e) {
            System.out.println("입력한 값은 숫자가 아닙니다.");
        }
    }
}

class Caculator {
    public void add(String a, String b) throws numberFormatException {
        int sum = Integer.parseInt(a) + Integer.parseInt(b);
        System.out.println("합 = " + sum);
    }
}
  • 메서드 선언부 옆에 작성

throw + throws

  • throw + throws를 같이 사용할 수 있다.
    • 예외를 한 번 더 처리하기 위해 강제로 발생시킴
public class Application {
    public static void main(String[] args) {
        Calculator calculator = new Calculator();
        try {
            calculator.add("1", "ㄱ");
        catch (NumberFormatException e) {
            System.out.println("입력한 값은 숫자가 아닙니다.");
        }
    }
}

class Caculator {
    public void add(String a, String b) throws numberFormatException {
        try {
            int sum = Integer.parseInt(a) + Integer.parseInt(b);
            System.out.println("합 = " + sum);
        } catch (NumberFormatException e) {
            System.out.println("숫자형 문자가 아닙니다. 형 변환을 할 수 없습니다.");
            throw e;
        }
    }
}
  • 호출한 메서드와 호출된 메서드에서 예외가 2번발생한다.
  • 예외처리를 분산하여 처리할 수 있다.

예외 처리 방법

1. 예외 복구

  • 예외 상황을 파알하고 문제를 해결해서 정상 상태를 돌려놓는 방법
  • 예외를 잡은 후 일정 시간과 조건만큼 대기하고 재시도를 반복한다.
  • 최대 재시도 횟수를 넘기면 예외를 발생시킨다.
final int MAX_RETRY = 100;

public Object retry() {
    int maxRetry = MAX_RETRY;
    while (maxRetry > 0) {
        try {
            ...
        catch (SomeException e) {
            maxRetry--;
            // 로그 출력
            // 정해진 시간만큼 대기
        } finally {
            // 리소스 반납 및 정리 작업
        }
    }

    throw new RetryFiledException();
}

2. 예외 처리 회피

  • 예외 처리를 직접 담당하지 않고 호출한 쪽으로 던져 회피하는 방법
  • 역할 분담이 명확한 것이 아니라면 그냥 예외를 던지는 것은 무책임하다. 어느 정도는 예외 처리를 하고 던지는 것이 좋다.
public void avoid1() throws SQLException {
    ...
}

public void avoid2() throws SQLException {
    try {
        ...
    catch (SQLException e) {
        ...
        throw e;
    }
}

3. 예외 전환

  • 예외 처리 회피처럼 그냥 던지지 않고 명확한 의미를 위해 적절한 예외로 전환해서 넘기는 방법
  • 예외 처리를 단순하게 만들기 위해 포장(wrap)할 수도 있다.
// 적합한 의미의 예외를 던지기
public void convert1(User user) throws DuplicateUserIdException, SLQException {
    try {
        ...
    catch (SQLException e) {
        if (e.getErrorCode() == MysqlErrorNumbers.ER_DUP_ENTRY) {
            throw new DuplicateUserIdException();
        } else {
            throw e;
        }
    }
}

// 단순 예외 포장
public void convert2() {
    try {
        ...
    } catch (NamingException ne) {
        throw new EJBException(ne);
    } catch (SQLException se) {
        throw enw EJBException(se);
    catch (RemoteException re) {
        throw new EJBException(re);
    }
}

출처

0개의 댓글