☕JAVA/🔎 공부 [JAVA]

[JAVA] 예외처리(Exception) / Throws

디카페인라떼 2022. 8. 13. 11:53

Exception

프로그램실행중 예기치 못한 사건을 예외라고 한다. 예외 상황을 미리 예측하고 처리할 수 있는데, 이렇게 하는 것을 예외 처리라고 한다.

    public class ExceptionExam {
        public static void main(String[] args) {
            int i = 10;
            int j = 5;
            int k = i / j;
            System.out.println(k);
            System.out.println(main 종료!!);
        }
    }
  • 위 코드에서 j를 0으로 바꾸면 Excption 발생
    • j를 0으로 바꾸면 ArithmeticException이 발생하면서 프로그램이 종료된다.
    • Java는 정수를 정수로 나눌때 0으로 나누면 안된다.0으로 나누면 오류가 발생하는 것입니다.
  • 예외 처리
    • 프로그래머는 j라는 변수에 0이 들어올지도 모르는 예외 상황을 미리 예측하고 처리할 수 있다.
  • 예외처리하는 문법 
    • 오류가 발생할 예상 부분을 try라는 블록으로 감싼 후, 발생할 오류와 관련된 Exception을 catch라는 블록에서 처리한다.
    • 오류가 발생했든 안했든 무조건 실행되는 finally라는 블록을 가질 수 있다.
    • finally블록은 생략가능하다.

    public class ExceptionExam {
        public static void main(String[] args) {
            int i = 10;
            int j = 0;
            try{
                int k = i / j;
                System.out.println(k);
            }catch(ArithmeticException e){
                System.out.println("0으로 나눌 수 없습니다. : " + e.toString());
            }finally {
                System.out.println("오류가 발생하든 안하든 무조건 실행되는 블록입니다.");
            }
        }
    }
  • 실행결과
    0으로 나눌 수 없습니다. : java.lang.ArithmeticException: / by zero

    오류가 발생하든 안하든 무조건 실행되는 블록입니다.
  • Exception 처리하지 않았을때는 프로그램이 강제 종료되었는데 catch라는 블록으로 Exception을 처리하니 강제종료되지 않고 잘 실행되는 것을 알 수 있다.
  • try블록에서 여러종류의 Exception이 발생한다면 catch라는 블록을 여러개 둘 수 있다.
  • Exception클래스들은 모두 Exception클래스를 상속받으므로, 예외클래스에 Exception을 두게 되면 어떤 오류가 발생하든지 간에 하나의 catch블록에서 모든 오류를 처리할 수 있다.

throws

throws는 예외가 발생했을때 예외를 호출한 쪽에서 처리하도록 던져준다.

    public class ExceptionExam2 {   
        public static void main(String[] args) {
            int i = 10;
            int j = 0;
            int k = divide(i, j);
            System.out.println(k);
        }

        public static int divide(int i, int j){
            int k = i / j;
            return k;
        }
    }

정수를 매개변수로 2개를 받아들인 후 나눗셈을 한 후 그 결과를 반환하는 divide메소드
main메소드에서는 divde메소드를 호출

다음과 같이 divide메소드를 수정

    public class ExceptionExam2 {

        public static void main(String[] args) {
            int i = 10;
            int j = 0;
            int k = divide(i, j);
            System.out.println(k);
        }

        public static int divide(int i, int j) throws ArithmeticException{
            int k = i / j;
            return k;
        }
    }

메소드 선언 뒤에 throws ArithmeticException 이 적혀있는 것을 알 수 있습니다. 이렇게 적어놓으면 divide메소드는 ArithmeticException이 발생하니 divide메소드를 호출하는 쪽에서 오류를 처리하라는 뜻입니다.

    package javaStudy;
    public class ExceptionExam2 {

        public static void main(String[] args) {
            int i = 10;
            int j = 0;
            try{
                int k = divide(i, j);
                System.out.println(k);
            } catch(ArithmeticException e){
                System.out.println("0으로 나눌수 없습니다.");
            }

        }

        public static int divide(int i, int j) throws ArithmeticException{
            int k = i / j;
            return k;
        }

    }

<Exception 발생시키기>

강제로 오류를 발생시키는 throw

throw는 오류를 떠넘기는 throws와 보통 같이 사용됩니다.

    public class ExceptionExam3 {   
        public static void main(String[] args) {
            int i = 10;
            int j = 0;
            int k = divide(i, j);
            System.out.println(k);

        }       
        public static int divide(int i, int j){
            int k = i / j;
            return k;
        }   
    }
  • divide메소드는 2번째 파라미터의 값이 0일 경우 나누기를 할 때 Exception이 발생한다.

위의 코드를 에러가 발생하지 않게 수정

    public class ExceptionExam3 {
        public static void main(String[] args) {
            int i = 10;
            int j = 0;
            int k = divide(i, j);
            System.out.println(k);      
        }

        public static int divide(int i, int j){
            if(j == 0){
                System.out.println("2번째 매개변수는 0이면 안됩니다.");
                return 0;
            }
            int k = i / j;
            return k;
        }
    }
  • j가 0일 경우 안된다는 메시지가 출력되도록 수정하고 0을 리턴.
  • 이렇게 할 경우 main메소드의 k변수는 0값을 가지게 되고 0을 출력하게 된다.
  • 0으로 나눈 결과는 0이 아니다. 0으로 반환하면 더 큰 문제가 발생할수도 있다.

에러도 발생하지 않고, 올바르지 않은 결과를 리턴하지 않도록 수정

    public class ExceptionExam3 {
        public static void main(String[] args) {
            int i = 10;
            int j = 0;
            int k = divide(i, j);
            System.out.println(k);

        }       
        public static int divide(int i, int j) throws IllegalArgumentException{//예외처리 던지기
            if(j == 0){
                throw new IllegalArgumentException("0으로 나눌 수 없어요.");//예외발생
            }
            int k = i / j;
            return k;
        }   
    }
  • j가 0일 경우에 new연산자를 통하여 IllegalArgumentException 객체가 만들어 진다.
  • new 앞에 throw 는 해당 라인에서 익셉션이 발생한다는 의미이다.
  • 즉 그 줄에서 오류가 발생했다는 것이다. 0으로 나눌수 없습니다. 라는 오류가 발생한것이다.
  • Exception클래스 이름을 보면 아규먼트가 잘못되었기 때문에 발생한 오류라는 것을 알 수 있다.

divide 메소드를 호출 한 쪽에서의 오류 처리

  • divide 메소드 뒤에 throws IllegalArgumentException 은 해당 오류는 divide를 호출한 쪽에서 처리를 해야한다는 것을 의미한다.
    public class ExceptionExam3 {   
        public static void main(String[] args) {
            int i = 10;
            int j = 0;
            try{
                int k = divide(i, j);
                System.out.println(k);
            }catch(IllegalArgumentException e){
                System.out.println("0으로 나누면 안됩니다.");
            }           
        }

        public static int divide(int i, int j) throws IllegalArgumentException{
            if(j == 0){
                throw new IllegalArgumentException("0으로 나눌 수 없어요.");
            }
            int k = i / j;
            return k;
        }   
    }

 

사용자 정의 Exception

  • Exception 클래스를 상속 받아 정의한 checked Exception
    • 반드시 오류를 처리 해야만 하는 Exception
    • 예외 처리하지 않으면 컴파일 오류를 발생 시킨다.
  • RuntimeException 클래스를 상속 받아 정의한 unChecked Exception
    • 예외 처리하지 않아도 컴파일 시에는 오류를 발생시키지 않는다.

RuntimeException을 상속받은 BizException객체

    public class BizException extends RuntimeException {
        public BizException(String msg){
            super(msg);
        }       
        public BizException(Exception ex){
            super(ex);
        }
    }

BizService클래스는 업무를 처리하는 메소드를 가지고 있다고 가정한다.

    public class BizService {
        public void bizMethod(int i)throws BizException{
            System.out.println("비지니스 로직이 시작합니다.");
            if(i < 0){
                throw new BizException("매개변수 i는 0이상이어야 합니다.");
            }
            System.out.println("비지니스 로직이 종료됩니다.");
        }
    }

앞에서 만든 BizService를 이용하는 BizExam클래스

  • 매개변수 값을 -1을 넘길때는 Exception이 발생하기 때문에 try catch블록으로 처리한다.
    public class BizExam {  
        public static void main(String[] args) {
            BizService biz = new BizService();
            biz.bizMethod(5);
            try{
                biz.bizMethod(-3);
            }catch(Exception ex){
                ex.printStackTrace();
            }
        }
    }

실행결과

비지니스 로직이 시작합니다.
비지니스 로직이 종료됩니다.
비지니스 로직이 시작합니다.
javaStudy.BizException: 매개변수 i는 0이상이어야 합니다.
at javaStudy.BizService.bizMethod(BizService.java:7)
at javaStudy.BizExam.main(BizExam.java:9)

'☕JAVA > 🔎 공부 [JAVA]' 카테고리의 다른 글

[JAVA] 기초 - 다시 정리하는 기본 개념  (0) 2022.08.18
[JAVA] objects.equals() 정리  (0) 2022.08.17
[JAVA] 내부클래스  (0) 2022.08.12
[JAVA] 인터페이스  (0) 2022.08.12
[JAVA] 메소드 - 오버라이딩  (0) 2022.08.10