티스토리 뷰

RuntimeException

RuntimeException은 주로 프로그래머의 실수에 의해 발생될 수 있는 예외를 의미합니다.

코드를 수정하여 해결할 수 있는 예외이기 때문에 잘 숙지하고 있어야 합니다.

 

예시는 다음과 같습니다.

 

배열을 벗어난 경우

ArrayIndexOutOfBoundsException

 

값이 null 인 참조변수의 멤버를 호출하려 한 경우

NullPointerException

 

클래스간 형변환을 잘못한 경우

ClassCastException

 

정수를 0으로 나누려고 한 경우

ArithmeticException

 

입력한 데이터 형식이 잘못된 경우

DataFormatException

 

예외처리(Exception Handling)

이러한 예외들을 미리 처리하여 실행중인 프로그램이 비정상적으로 종료되는 것을 막습니다.

이를 예외처리(Exception Handling) 이라고 합니다.

 

이렇게 발생한 예외를 처리하지 못하면 프로그램이 비정상적으로 종료되고,

처리되지 못한 예외(uncaught exception)을 JVM 의 예외처리기(UncaughtExceptionHandler)

가 받아서 예외의 원인을 화면에 출력합니다.

 

비정상적인 종료를 막아야 겠죠?

 

예외를 어떻게 처리할까요?

try-catch 구문을 사용하면 됩니다.

 

try-catch 구문

하나의 try 블럭 다음에는 여러 개의 catch 블럭이 올 수 있고,

이 중 발생한 예외의 종류와 일치하는 단 하나의 catch 블럭만 수행됩니다.

발생하는 예외의 종류와 일치하는 catch 블럭이 없으면 예외는 처리되지 않습니다.

 

예외의 종류와 일치하는지는 어떻게 확인할까요?

 

try {

} catch (Exceptionclass e) {

} catch (Exceptonclass2 e) {

}

 

try 문에서 예외가 발생하면 발생한 예외에 해당하는 클래스의 인스턴스가 만들어집니다.

첫 번째 catch 블럭부터 내려가면서, catch 블럭의 괄호 내()에 선언된 참조변수의 종류와

생성된 예외클래스의 인스턴스에 isinstanceof 연산자를 이용해서 검사합니다. 

결과가 true 이면 블럭{} 의 문장을 모두 수행한 후 try-catch 문을 빠져나갑니다.

 

모든 예외 클래스는 Exception 클래스의 자손이기 때문에, (Exception e) 클래스 타입의 참조변수를

캐치 블럭 괄호()에 선언해 놓으면 어떤 종류의 예외라도 해당 캐치 블럭에 의해 처리가 되겠습니다.

 

 

에러를 고의로 발생시키기

throw 라는 키워드를 많이 보았는데요, throw를 사용해서 프로그래머가 고의로 예외를 발생시키는 것입니다.

이 부분이 낯설게 느껴졌는데요, 왜 이렇게 하는지 이유를 알면 이해가 되겠습니다.

 

대표적인 이유는 로직에서 예외를 발생시켜야 하는 경우입니다.

예를 들어서, 비밀번호로 영문자, 숫자, 특수문자를 하나씩 넣어야만 통과된다는 로직이 있다고 했을 때,

해당 로직을 통과하지 못한다고 해서 프로그램이 멈추지 않습니다.

하지만 해당 로직을 통과하지 못하게 해야 하기 때문에 고의로 예외를 발생시키는 것입니다.

 

고의로 예외를 발생시키는 것은 아니지만, 예외를 직접 만들어내는 경우도 있습니다.

이는 구체적으로 예외를 확인하기 위해서입니다.

예를 들어서, 데이터를 읽어오는데 '제목' 정보에서 빈 문자열 ""이 반환되어 타입캐스팅 에러가 발생했다고 해봅시다.

이 경우 제가 볼 수 있는 에러는 타입캐스팅 에러 뿐입니다.

하지만 '제목' 데이터에 문제가 있다는 것을 구체적으로 명시해주고 싶다면 에러를 직접 정의내려서 사용하면 되겠습니다.

 

 

메서드에 예외 선언하기

예외가 발생한 메서드 내에서 자체적으로 처리해도 되는 것은 메서드 내에서 try-catch 문을 사용해 처리하면 됩니다.

반면, 메서드 내에서 해결되지 않는 경우에는 예외를 메서드에 선언한 후, 호출한 메서드에서 처리해야 합니다.

이 경우에는 호출 메서드(예를 들면 main 메서드) 에 try-catch 문이 사용되고, 호출한 메서드의 선언부에 throws 로 예외를 선언합니다.

// 예외를 메서드에 선언해서, 호출한 main 메서드에서 처리
public class ExceptionEx16 {
    public static void main(String[] args) {
        try {
            File f = createFile(args[0]);
            System.out.println(f.getName() + "file produced");
        } catch (Exception e) {
            System.out.println(e.getMessage() + "rewrite file name");
        }
    }

    static File createFile(String fileName) throws Exception {
        if (fileName == null || fileName.equals("")) {
            throw new Exception("invalid file name");
        }
        File f = new File(fileName);
        f.createNewFile();
        return f;
    }

 

예외처리를 선택적으로 할 수 있는 RuntimeException 을 상속받아서 사용자 예외처리를 만들 수 있습니다.

메서드에 예외를 선언하면 이 메서드를 사용하기 위해서는 어떤 예외를 처리해야 하는지 명확하게 알 수 있습니다.

 

throws는 예외를 선언하는 키워드이고, throw는 예외를 발생시키는 키워드입니다.

throws로 예외를 선언하지 않아도 생성만 해주면 동작에는 문제가 없습니다.

 

그렇지만 메서드 선언부에 메서드를 사용할 때 발생할 가능성이 있는 예외를 적어주면

프로그램이 더욱 견고해지고 의사소통도 쉬워질 것입니다.

 

public class NewExceptionTest {
    public static void main(String[] args) {
        try {
            startInstall();
            copyFiles();
        } catch (SpaceException e) {
            System.out.println("error msg : " + e.getMessage());
            System.out.println("공간을 확보해주세요.");
        } catch (MemoryException me) {
            System.out.println("error msg : " + me.getMessage());
            System.out.println("다시 설치를 시도하세요.");
        } finally {
            deleteTempFiles();
        }
    }

    static void startInstall() throws SpaceException, MemoryException { // 발생할 수 있는 예외를 선언 (적지 않아도 문제없음)
        if (!enoughSpace())
            throw new SpaceException("설치할 공간이 부족합니다."); // 예외를 생성 
        if (!enoughMemory())
            throw new MemoryException("메모리가 부족합니다.");
    }

    static void copyFiles() {}
    static void deleteTempFiles() {}

    static boolean enoughSpace() { return true; }
    static boolean enoughMemory() { return false; }
}

class SpaceException extends RuntimeException {
    SpaceException(String msg) {
        super(msg);
    }
}

class MemoryException extends RuntimeException {
    MemoryException(String msg) {
        super(msg);
    }
}
error msg : 메모리가 부족합니다.
다시 설치를 시도하세요.

 

코드 출처

자바의 정석 

댓글