🏃♂️ 들어가기 앞서..
본 게시물은 스터디 활동 중에 작성한 게시물로 자바의 정석-기초편 교재를 학습하여 정리하는 글입니다.
※ 스터디 Page : 〔투 비 마스터 : 자바〕
*해당 교재의 목차 순서와 구성을 참고하여 작성하며
각 내용마다 부족할 수 있는 내용이나 개인적으로 궁금한 점은
추가적인 검색을 통해 채워나갈 예정입니다.
지난 글부터 다뤄봤을 때
Java에 Exception
클래스가 있는 것을 알 수 있었는데
이 클래스를 활용해서
사용자가 직접 예외 클래스를 정의할 수 있다.
방법은
이 Exception
클래스 ( 사용자 발생 필수처리 ) 나
RuntimeException
클래스 ( 프로그래머 실수 발생 선택처리 ) 중
하나를 선택해서 상속시키면 된다.
class MyException extends Exception {
MyException(String msg) { // 문자열을 매개변수로 받는 생성자
super(msg); // 조상인 Exception클래스를 super() 조상 생성자로 호출
}
}
조금 더 구체화 시켜본다면
class MyException extends Exception { // Exception 클래스는 try-catch 필수 처리
private final int ERR_Code ; // (private 상수) 생성자를 통해 초기화
MyException(String msg, int errCode) { // 문자열을 매개변수로 받는 생성자
super(msg); // 조상인 Exception클래스를 super() 조상 생성자로 호출
ERR_Code = errCode;
}
MyException(String msg) { // 생성자
this(msg, 100); // ERR_Code를 기본값 100으로 초기화
}
public int getErrCode() { // 에러코드 얻는 메서드 추가
// 메서지는 getMessage()를 통해 얻을 수 있기 때문에 별도로 할 필요 없음.
return ERR_Code ;
}
}
위 클래스를 통해
MyException
이 발생했을 때,
catch블럭에서 getMessage()
와 getErrCode()
를 활용할 수 있다.
( try-catch
문을 필수적으로 작성하는 Exception
클래스를 활용해서 만들게되면 복잡해지기 때문에 RuntimeException
을 주로 사용한다고 한다. )
exception re-throwing
)" 예외를 처리한 후 ", 다시 예외를 발생시키는 것
기껏 처리했는데 다시 발생시킨다니...
이게 무슨 헛소리인가 싶었지만
" 하나의 예외 "에 대해서
<예외가 발생한 메서드> 와 이를 <호출한 메서드>
" 양쪽 모두에서 처리해줘야 할 작업 이 있을 때 " 사용된다.
( 예외 처리한 것에 대한 추가적인 처리가 필요할 때 )
먼저
<예외가 발생할 가능성이 있는 메서드> 에서
try-catch
문을 사용해서 예외를 처리해주고
catch
문에서 필요한 작업을 행한 후
throw
문을 사용해서 예외를 다시 발생시킨다.
이 재발생한 예외는
" 호출한 메서드 "에 전달되고
" 호출한 메서드의 try-catch
문 "에서 또 예외를 처리하는 방식이다.
public static void main(String[] args) {
try {
method1();
} catch (Exception e) {
System.out.println("main메서드 예외 처리");
}
}
static void method1() throws Exception { // throws로 예외 선언 필요
try {
throw new Exception();
} catch (Exception e) {
System.out.println("method1메서드 예외 처리");
throw e; // 다시 예외 발생시켜서 main메서드로 예외 전달
}
}
위 코드에서 봤듯이
예외가 발생할 메서드에서
try-catch
문을 사용해 예외 처리를 해줌과 동시에
" 메서드 선언부 "에
발생할 예외를 throws
에 지정해주어야 한다.
chained exception
)" 한 예외가 다른 예외를 발생시킬 때의 인과관계 "
인과관계를 나타내고
서로 발생에 대한 연관성을 나타낼 수 있는데
예를 들어
예외 A가 " 예외 B를 발생시킨다. " 라면
예외 A는 " 예외 B의 원인예외(cause exception) "라고 칭한다.
Throwable initCause(Throwable cause)
: 지정예외(Throwable cause
)를 원인예외로 "등록"Throwable getCause()
: 원인예외를 "반환 "( Throwable
클래스 = Exception
클래스 & Error
클래스의 조상클래스 )
이렇게 관계를 정립시키는 이유는
① 여러가지 예외를
" 하나의 큰 분류의 예외로 묶어서(포함시켜) 다루기 " 위해서이다.
void install() throws InstallException { //아래처럼 발생한 예외를 포함시켜 다시 던지는 구조
try {
startInstall(); // SpaceException이 발생하게되면 첫번째 catch문으로 이동
copyFiles();
} catch (SpaceException se) { //예외 A
InstallException ie = new InstallException("예외 발생") ; // 예외 생성 _ 예외B
ie.initCasue(se) ; // InstallException의 "원인예외"로 SpaceException을 지정
throw ie; // InstallException로서 발생시키기
// SpaceException을 InstallException로 포함시켜
// InstallException이 발생된 것으로 만듦
} catch (MemoryException me) {
...
}
}
위 메서드를 사용하게되면
try {
install() ;
} catch (SpaceException e) {
e.printStackTrace();
} catch (MemoryException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
/*
위와같은 반복적인 catch를
아래처럼 큰 범위로 관리할 수 있다.
*/
try {
install();
} catch(InstallException e) {
e.printStackTrace();
} catch(Exception e) {
e.printStackTrace();
}
② checked예외를 " unchecked예외로 변경하려 할 때 사용
이미 알아봤지만
checked예외는 필수처리를 해야하기 때문에
강제로 복잡한 try-catch
문이 작성될 수도 있는데
unchecked로 바꾸게 된다면
선택적으로 변경되는 것이다.
/*
이 SpaceException클래스는 Exception클래스를 상속받은 상태로 생성이 되기때문에
try-catch문의 굴레에서 벗어나기 힘든 상태이다
*/
class SpaceException extend Exception {
SpaceException(String msg) {
super(msg) ;
}
}
/*
이때 연결된 예외를 활용하여
어떠한 checked 예외를
unchecked예외 클래스에 "포함" 시켜서
unchecked 예외클래스 중 하나인 것처럼 위장시켜서
처리문에서 자유롭게 만들어줄 수 있다.
*/
static void startInstall() throws SpaceException, MemoryException { //둘다 필수처리
if (!enoughSpace())
throw new SpaceException("설치 공간 부족") ;
if (!enoughMemory())
throw new MemoryException("메모리 부족") ;
}
/*
위 코드를 ↓
*/
static void startInstall() throws SpaceException { //MemoryException을 선택처리로 바꾸기 위해 제외
if (!enoughSpace())
throw new SpaceException("설치 공간 부족") ;
if (!enoughMemory())
// initCasue() 대신 RuntimeException 생성자에 작성함
throw new RuntimeException(new MemoryException("메모리 부족")) ; //포함시키기
// RuntimeException(Throwable cause) 방법으로도 원인예외로 등록 가능
//MemoryException unchecked화
}