2021-9-14 점프 투 자바 예외처리

7-4 예외처리 (Exception), 트랜잭션

BufferedReader br = new BufferedReader(new FileReader("나없는파일"));
br.readLine();
br.close();

--------------------------------------------------------
int c = 4 / 0;

--------------------------------------------------------

int[] a = {1, 2, 3};
System.out.println(a[3]);

위 코드들을 실행하면 오류가 발생한다.


예외 처리하기

try {
    ...
} catch(예외1) {
    ...
} catch(예외2) {
    ...
...
}

try문 안의 문장들을 수행중 해당예외가 발생하면 예외에 해당되는 catch문이 수행된다.

int c;
try {
    c = 4 / 0;
}catch(ArithmeticException e) {
    c = -1;
}

ArithemicException 이 발생하면 c 에 -1을 대입하도록 예외처리한 것이다.

finally

예외가 발생하더라도 반드시 실행되어야 하는 부분이 있으면 사용한다.

public class Test {
    public void shouldBeRun() {
        System.out.println("ok thanks.");
    }

    public static void main(String[] args) {
        Test test = new Test();
        int c;
        try {
            c = 4 / 0;
            test.shouldBeRun();
        } catch (ArithmeticException e) {
            c = -1;
        }
    }
}

위의 코드에서는 test.xhouldBeRun()이라는 메소드는 절대 실행될 수 없다.

public class Test {
    public void shouldBeRun() {
        System.out.println("ok thanks.");
    }

    public static void main(String[] args) {
        Test test = new Test();
        int c;
        try {
            c = 4 / 0;
        } catch (ArithmeticException e) {
            c = -1;
        } finally {
            test.shouldBeRun();
        }
    }
}

반드시 실행되어야 하는 부분은 finally 구문을 사용하여 실행시킨다.


예외 발생시키기

public class Test {
    public void sayNick(String nick) {
        if("fool".equals(nick)) {
            return;
        }
        System.out.println("당신의 별명은 "+nick+" 입니다.");
    }

    public static void main(String[] args) {
        Test test = new Test();
        test.sayNick("fool");
        test.sayNick("genious");
    }
}

위의 코드는 fool이라는 문자열이 입력되면 return으로 메소드를 종료해 출력되지 못하게 하고있다.

다음은 적극적으로 예외를 발생시키는 방법이다.

RuntimeException

//FoolException.java

public class FoolException extends RuntimeException {
}
public class Test {
    public void sayNick(String nick) {
        if("fool".equals(nick)) {
            throw new FoolException();
        }
        System.out.println("당신의 별명은 "+nick+" 입니다.");
    }

    public static void main(String[] args) {
        Test test = new Test();
        test.sayNick("fool");
        test.sayNick("genious");
    }
}

위 프로그램을 실ㄹ행시키면 다음과 같은 예외가 발생한다.

Exception in thread "main" FoolException
    at Test.sayNick(Test.java:7)
    at Test.main(Test.java:15)

main 메소트에서 예외를 처라하는 방법도 있다.

public void sayNick(String nick) throws FoolException {
    if("fool".equals(nick)) {
        throw new FoolException();
    }
    System.out.println("당신의 별명은 "+nick+" 입니다.");
}

메소드 뒷부분에 throws 라는 구문을 이용하여 FoolException을 위로 보낼 수가 있다.

public static void main(String[] args) {
    Test test = new Test();
    try {
        test.sayNick("fool");
        test.sayNick("genious");
    }catch(FoolException e) {
        System.err.println("FoolException이 발생했습니다.");
    }
}

메인 메소드는 다음과 같이 예외처리를 한다.

하지만 메인 메소드에서 다음과 같이 예외처리를 한 경우에는 두번 째 문장인 test.sayNick(“genious”)가 수행되지 않을 것이다.


트랜잭션(Transaction)

트랜잭션은 하나의 작업단위를 뜻한다.

다음은 예시로 쇼핑몰의 “상품발송” 이라는 트랜잭션을 가정해보았다.

  • 포장
  • 영수증발행
  • 발송

이 3가지 일들 중 하나라도 실패하면 3가지 모두 취소하고 “상품발송” 전 상태로 되돌리고 싶을 것이다.

상품발송() {
    포장();
    영수증발행();
    발송();
}

포장(){
    try {
       ...
    }catch(예외) {
       포장취소();
    }
}

영수증발행() {
    try {
       ...
    }catch(예외) {
       영수증발행취소();
    }
}

발송() {
    try {
       ...
    }catch(예외) {
       발송취소();
    }
}

만약 위와같이 메소드에 예외가 처리되어 있다면 포장은 되었는데 발송은 안되고 포장도 안되었는데 발송이되는 뒤죽박죽의 상황이 발생할 것이다.

그래서 아래와 같이 코드를 작성하면 포장, 영수증발행, 발송이라는 3개의 단위작업중 하나라도 실패할 경우 예외가 발생되어 모두 취소될것이다.

상품발송() {
    try {
        포장();
        영수증발행();
        발송();
    }catch(예외) {
       모두취소();
    }
}

포장() throws 예외 {
   ...
}

영수증발행() throws 예외 {
   ...
}

발송() throws 예외 {
   ...
}
Written on September 14, 2021