도서 자바의신을 참고하였습니다.
java.lang.Throwable
은 Error
와 Exception
을 포함한 최상위 클래스입니다. Error는 자바 프로그램 밖에서 발생한 예외로, 프로세스에 영향을 미치지만 Exception은 해당 쓰레드에만 영향을 줍니다.
Exception은 다시 RuntimeException(=UncheckedException)
과 CheckedException
으로 나뉩니다. RuntimeException은 컴파일 시 체크되지 않으므로 예외가 발생한 것을 미리 감지하지 못할 때 발생합니다. 이와 반대로 CheckedException은 java.lang.Exception
을 확장한 클래스들로 컴파일 시 체크 가능합니다.
Exception과 Error의 공통 부모 클래스는 java.lang.Throwable
클래스입니다. Exception와 Error의 성격은 다르지만, 모두 동일한 이름의 메소드를 사용하여 처리하기 위해 동일한 부모 클래스를 상속받으며, Exception과 Error를 처리할 때 Throwable
로 처리해도 됩니다.
Throwable 생성자에는 위 4가지 생성자가 있으며, 매개변수인 Throwable cause
를 통해 별도의 예외 원인을 객체로 넘겨줄 수 있습니다.
public String getMessage()
: 예외 메시지를 String 형태로 제공받음. 어떤 예외가 발생했는지 확인할 때 유용함.public String getLocalizedMessage()
: 로컬 예외 메시지를 받지만, 특정 클래스에서 이 메소드가 재정의되어 있지 않은 경우 getMessage()와 동일한 결과값을 리턴함.public String toString()
: getMessage()보다 더 자세하게 예외 클래스명도 제공함.public void printStackTrace()
: 매우 자세하게 어디서 무슨 예외가 발생했는지 알려주기 때문에 운영에 배포될 소스에는 사용하면 안됨.public class ExceptionMain {
public static void main(String[] args) {
try {
crunch(null);
} catch (NullPointerException e) {
//System.out.println(e.getMessage()); //null
//System.out.println(e.getLocalizedMessage()); //null
//System.out.println(e.toString()); //java.lang.NullPointerException
e.printStackTrace();
//java.lang.NullPointerException
// at com.test.exception.ExceptionMain.mash(ExceptionMain.java:19)
// at com.test.exception.ExceptionMain.crunch(ExceptionMain.java:16)
// at com.test.exception.ExceptionMain.main(ExceptionMain.java:6)
}
}
static void crunch(int[] a) {
mash(a);
}
static void mash(int[] b) {
System.out.println(b[0]);
}
}
throws
키워드는 예외가 발생된 메소드를 다시 호출한 메소드로 던지는 것을 말합니다. 이미 throws한 것을 다시 throws 하는 것은 별로 좋지 않습니다. 가장 좋은 방법은 throws하는 메소드를 호출하는 메소드에서 try~catch
로 처리하는 방법입니다. 메소드를 throws할 때는 2가지 이상의 예외를 던질 수도 있습니다.
try 블록 내에서 예외를 발생시킬 경우에는 다음과 같이 throw
예약어를 적어둔 뒤 예외를 객체를 생성하거나 예외 클래스명을 명시해야 합니다.
public static void main(String[] args) {
try {
throw new MyException("m");
} catch (MyException e) {
e.printStackTrace();
}
}
만약 throw한 예외 클래스가 catch 블록에 선언되어 있지 않거나, throws에 선언되어 있지 않다면 컴파일 에러가 발생합니다. catch 블록에서 예외를 throw할 경우에도 메소드 선언의 throws 구문에 해당 예외가 정의되어 있어야 합니다.
Throwable이나 Exception 클래스를 상속 받으면 커스텀 예외 클래스를 생성할 수 있습니다. 하지만, Throwable은 Exception말고도 Error를 자식클래스로 포함하기 때문에, Exception 클래스 상속받는 것을 더 추천합니다.
만약 커스텀 예외 클래스에서 extends Exception
을 통해서 만들었지만, 런타임 시에 예외가 발생할 확률이 더 높다면 extends RuntimeException
으로 선언하는 것이 좋습니다. 이렇게 변경하면 해당 예외를 throw하는 메소드를 사용하더라도 try~catch문으로 묶지 않아도 컴파일 에러가 발생하지 않습니다. 하지만, 이 경우에는 예외 발생 시 해당 클래스를 호출하는 다른 클래스에서 예외를 처리하도록 구조적인 안전 장치(호출하는 메소드에서 try~catch문이 있어야 함)가 되어 있어야 합니다.
public void methodCaller() {
try {
methodCallee();
} catch(Exception e) {
//예외 처리
}
}
public void methodCallee() {
//RuntimeException 발생 가능성 있는 부분
//여기서 try~catch문이 없다면 methodCaller에 있어야 함.
}
지속적으로 수정해나갈 예정입니다.
2023-07-22 v1.0
자바 예외처리에 대한 글 잘 읽었습니다. 각 예외들과 Throwable 클래스가 어떻게 작동하는지, 그리고 어떻게 사용하는지에 대한 설명이 상세하게 잘되어 있어서 이해하는데 도움이 되었습니다. 이와 같은 효과적인 예외 처리 전략에 대한 정보는 프로그래밍을 하면서 매우 중요하므로, 이 포스트를 참조하면서 제 코드에 적용해볼 생각입니다. 감사합니다.