Java/모두의 자바

Chapter 09-51 사용자 정의 Exception

계란💕 2022. 2. 12. 16:07

09-51.1  Exception

  - 앞서 배웠듯이 Exception클래스는 이미 자바에서 정의된 클래스를 이용할 수도 있고 사용자가 직접 정의할 수 있다.

public class 클래스명 extends Exception{
	...
}

  - 사용자는 Exception이나 RuntimeException 클래스를 상속 받아 새로운  Exception 클래스를 만들 수 있다. 

  - 새로운 Exception클래스를 만드는 이유는 클래스명만 봐도 어떤 오류가 발생했는지 직관적으로 알려주기 위해서다.

  -  Exception을 상속 받은 클래스를 Checked Exception이라고 한다. 

  - 에러 처리를 하지 않으면 컴파일 에러가 발생하기 때문에 반드시 에러를 처리해야 하는 Exception을 말한다.

  - RuntimeException을 상속 받아 정의한 Exception은 에러 처리하지 않아도 컴파일 상에서 에러를 발생시키지 않는다. 

   - 하지만 모든 예외사항을 적절하게 처리해줘야 프로그램을 안정적으로 수행가능하다. 

  

 

09-51.2 BizService라는 클래스를 만들어 알아보자

 

  Ex) 사용자 정의 Exception 

<hide/>
package javaStudy;
public class BizException extends RuntimeException {
	public BizException(String msg) {
		super(msg);
	}
	public BizException(Exception ex) {
		super(ex);
	}
}

  - BizService는 업무와 관련한 기능이 있다. 

  - 업무 관련 메서드를 비즈니스 메서드라고 한다. 

  - 업무와 관련한 Exception이 발생하면 해당 메서드를 호출한 쪽으로 알려줘야한다.

  - 이를 위해 RuntimeException을 상속 받은 BizException객체를 만들어보자

  - Exception을 상속받은 BizException을 만든다. 

  - Exception을 상속 받으면 checked/ unchecked 으로 나뉜다.

  - RuntimeException을 상속 받으면 unchecked Exception으로 생성 가능하다. 

  - public BizException(String msg) {super(msg);}

    -> BizException에서 어떤 에러가 났는지 String 값으로 메시지를 가져오는 생성자를 만든다. 

    -> 메시지를 가져와서 super에 메시지를 보내는 생성자이다.

  - public BizException(Exception ex) {super(ex);}

    -> Exception를 받아들여 해당 Exception을 부모 생성자에게 넘겨주는 생성자를 만든다. 

  - 정리: RuntimeException을 상속 받은 후에 생성자를 두 개 정의한다.

  - 문자열로 된 에러 메시지와 실제 발생한 Exception을 담기 위한 생성자 두 개를 선언한다.

  

 

09-51.3  Exception을 사용하는 클래스 만들기

<hide/>
package javaStudy;
public class BizService {
	public void bizMethod(int i) throws BizException{
		System.out.println("비즈니스 메서드 시작");
		if(i < 0)
			throw new BizException("매개변수 i는 0이상이어야 한다.");
		System.out.println("비즈니스 메서드 종료");
	}	
}
<hide/>
package javaStudy;
public class BizExam {
	public static void main(String[] args) {
		BizService biz = new BizService();
		biz.bizMethod(5);		
		biz.bizMethod(-3);
		System.out.println("프로그램 종료");
	}
}

  Note) 실행 결과

  - BizService 클래스에 비즈니스를 수행하는 bizmethod를 하나 정의한다. 

  - bizmethod는 int를 받아들이고 Exception이 발생했을 때 throws를 이용해 BizException을 넘겨주는 로직으로 작성한다.  

  - 매개변수로 들어온 i가 0보다 작을 경우 Exception을 발생시킨다. 

  - BizService는 RuntimeException을 상속 받는 메서드를 throw한다.

  - 그래서 Exception처리하라고 컴파일 에러가 나지는 않는다. 

  - -3을 인자로 가진 두 번째 메서드를 호출했을 때 실제 메서드를 실행하는 부분에서 인자가 0보다 작다.

  - 그러면 BizException을 발생시키고 해당 메서드는 BizException을 throws시킨다. 

  - 그런데 main메서드에서 예외를 처리하지 않기 때문에 해당프로그램을 끝까지 실행시키지 않고 종료한다.

  - 따라서 프로그램 종료 라는 문자열을 정상적으로 출력하지 못한다. 

  -  unchecked Exception이 발생하더라고 예외를 제대로 처리하지 못하면 프로그램을 종료한다.

  - 그러므로 예외 발생하는 상황에 대해 예외처리는 잘 해줘야 한다. 

  

 

09-51.4  try-catch 문 예외처리

<hide/>
package javaStudy;
public class BizExam {
	public static void main(String[] args) {
		BizService biz = new BizService();
		biz.bizMethod(5);	
		try{
			biz.bizMethod(-3);
		}catch(Exception e) {
			e.printStackTrace();
		}
		System.out.println("프로그램 종료");
	}
}

  Note) 실행 결과

  - i = -3이 들어로면 Exception을 발생시킨다. 

  - 예외 발생한 상황은 같지만 메서드를 호출할 때 예외를 잘 처리했기 때문에 프로그램을 그냥 종료하지 않는다.

  - 예외를 잘 처리하고 다음 부분을 정상적으로 수행한다.

  - Checked Exception, Unchecked Exception의 차이점은 컴파일 시에 컴파일 에러를 미리 발생시켜서 반드시 예외를 처리할 것인지 여부이다.

  - 이 부분만 다르고 실행 시에는 똑같다. 

 

 

09-51.5 사용자 정의 Exception 실습

 

  Ex 1) MyCheckException 클래스가 checked Exception이 되도록 만들라. 그리고 MyCheckException이 발생했을 때

  "나의 예외발생"이라는 메시지가 나올 수 있도록 생성자를 추가하라.

<hide/>
package javaStudy;
public class MyCheckedException extends Exception {
//정답	public MyCheckedException() {
//		super("나의 예외 발생");
	}
}

  - RuntimeException class를 상속 받으면 UncheckedException이 되고

  - Exception class를 상속 받으면 Checked Exception이 된다. 

  - 기본 생성자의 super 메서드를 호출할 때 인자로 해당 메시지를 넣어준다. 

 

 

09-51.6 사용자 정의 Exception 실습

 

  Ex 2) Ex 1) 에서 작성한 MyCheckException 참고한다.

<hide/>
package javaStudy;
public class ExceptionExam {
	public static void main(String[] args) {
		ExceptionExam exam = new ExceptionExam();
		int [] array = new int[10];
//정답  try {
//			exam.get50thItem(array);
//		}catch(Exception e) {
//			System.out.println(e);
//		}	
	}
	public int get50thItem(int [] array) throws MyCheckedException{
		if( array.length < 50 ) {
			throw new MyCheckedException();
		} 
		return array[49];
	}	
}

  Note) 실행 결과

  - Checked는 반드시 예외를 처리해야하는 Exception이다.

  - get50thItem메서드는 반드시 예외를 처리해야하는 checked Exception인 MyCheckedException을 throws한다.

  - 따라서 사용하는 쪽에서 예외처리해야한다.  (처리하지 않으면 컴파일 에러)

  - 예외처리할 방벙은 catch블록에 구현한다. 

  - 특별한 요구 사항이 없으면 비워도 된다.

  - 그러나 모든 예외를 처리하는 catch블록은 실제 예외가 발생했을 때 어떤일도 하지 않고 지나친다.

  - 그러므로 특별히 처리할 내용이 없다면 해당 예외 내용을 알려주는 것이 좋다. 

  - 따라서 콘솔애 예외를 출력하는 System.out.println(e);이나 e.printStackTrace() 중 하나를 구현하는 것이

  - 비워두는 것보다 훨씬 좋다.