Exception 예외 처리

준우·2022년 4월 25일
1

Java

목록 보기
9/30
post-thumbnail

예외 처리

만약 Java 코드에 오류가 있으면, 프로그램은 실행되지 않고 종료된다.

public class ExceptionExam {
        public static void main(String[] args) {
            int i = 5;
            int j = 0;
            int k = i / j;
            System.out.println(k);
            System.out.println(main 종료!!);
        }
    }

예를 들어, 위와 같은 코드를 실행시키면 ArithmeticException 오류가 발생하며 프로그램이 종료된다.
Java에서는 정수를 0으로 나눌 수 없기 때문이다.
그런데 예외처리를 통해서 오류가 발생하더라도 이를 무시하고 프로그램을 실행 시킬 수 있다.

try-catch-finally

그 방법은 try-catch-finally를 사용하는 것이다.
기본 형태는 아래와 같다. 여기서 finally는 생략이 가능하며, 필수가 아니다.

try{
	/* 예외가 발생할 가능성이 있는 블록 */
    // 수행할 코드
    
} catch(예외클래스 변수명){
	/* try블록에서 오류 발생 시 catch 블록으로 이동 */
    /* 발생 오류와, 예외 클래스 변수명에 지정한 오류가 일치해야 작동 */
    
} finally { 
	/* 오류가 발생했든, 안했든 무조건 실행 */
	...
}

try{} 블록에는 오류가 발생할 가능성이 있는 코드를 입력하고,
catch의 () 안에는 발생할 오류클래스타입과 변수명을 적는다.(ex. ArithmeticException e)
오류클래스는 "," 를 사용하여 여러 개를 지정할 수도 있다.
그리고 catch의 {} 블록에는, try{}에서 정말 오류가 발생한다면 실행할 코드를 입력한다.
finally{}는 오류가 발생했든, 하지 않든 무조건 실행할 코드가 있다면 입력한다.

여기서 주의할 점은 try-catch를 통해 예외처리를 한다고 하더라도,
무조건 catch 블록이 작동하는 것은 아니다.

발생한 오류가 catch()에 입력한 예외 클래스 변수명과 다를 경우에는
catch 블록이 작동하지 않기 때문이다.

이 때, 필요 시 finally를 통해 오류 여부와 관계없이 무조건 실행할 코드를 작성할 수 있다.

적용 예시

public class ExceptionExam {
        public static void main(String[] args) {
            int i = 5;
            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("오류와 관계없이 실행되는 문장입니다.");
            }
        }
    }

위 코드는 맨 앞에서 예시로 들었던 오류 코드에 try-catch-finally를 적용한 것이다.
catch{}에 발생한 오류 클래스타입을 적고 변수명을 e로 지정했다.
이제는 프로그램이 종료되는 대신 "정수는 0으로 나눌 수 없습니다." 문장이 출력된다.
그리고 e.toString() 을 통해서 예외 정보를 출력할 수 있다.
이후 finally{} 도 실행된다.

Exception 클래스

모든 예외는 Exception 클래스를 상속받으므로, catch() 괄호 안에
Exception 타입을 지정한다면 하나의 블록에서 모든 오류를 처리할 수 있다.

Throws

메소드를 정의할 때에도 throws 를 사용해 예외를 지정하면 오류가 발생했을 때,
해당 메소드 정의한 쪽에서 직접 예외처리를 하는 게 아니라
메소드를 호출하는 쪽에서 예외를 처리하도록 떠넘길 수 있다.

예를 들어 아래와 같은 메소드가 있고, throws를 사용했다.
*여기서 예외클래스의 변수명은 지정하지 않아도 된다.

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

아래처럼 divide() 메소드를 호출하는 쪽에서 try-catch문을 사용해
예외를 처리해야한다.

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으로 나눌 수 없습니다.");
            }

        }

Throw

throws가 아니라, throw 는 인위적으로 Exception을 발생시키고 싶을 때 사용한다.

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

애초에 정수를 0으로 나누어 오류가 날 코드라면 아래처럼 if 문을 통해 방지할 수 있을 것이다.

public static int divide(int i, int j){
            if(j == 0){
                System.out.println("2번째 매개변수는 0보다 커야 합니다.");
                return 0;
            }
            int k = i / j;
            return k;
        }

그런데 return type이 int 인 관계로 어쩔 수 없이 숫자를 리턴해야하는데,
오류인 경우에는 숫자를 리턴하고 싶지 않다.
이럴 때 throw를 사용해 int가 0이면 오류를 발생시키는 것이다.

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

그리고 그 발생하는 오류는 throws를 통해 메소드 호출 시 해결하도록 구현할 수 있다.

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으로 나눌 수 없습니다.");
            }           
        }

Reference 🙏

0개의 댓글