☕Java: Exception (2) 사용자정의 예외, 강제 예외발생, 예외의 변환

yoondgu·2022년 4월 18일
0

Java 

목록 보기
12/18

강의 수강 중 작성한 노트에서 내용을 발췌, 이응수 강사님 강의 의 노트와 이미지를 참조하고 있습니다.
스스로 이해를 위해 직접 쓴 문장들의 경우 정확성이 떨어질 수 있다는 점 참고 부탁드립니다.

사용자정의 예외, 강제 예외발생, 예외의 변환


📌 사용자정의 예외클래스

  • Checked 예외클래스 만들기: Exception 클래스를 상속받는다.

    • 이는 예외처리를 강제하는 예외클래스를 정의하는 것이다.
  • Unchecked 예외클래스 만들기: RuntimeException 클래스를 상속받는다.

    • 이는 예외처리를 강제하지 않는 예외클래스를 정의하는 것이다.
    • 현재는 대부분 Unchecked 사용자정의 예외클래스를 선호한다.
  • 작성방법

    • 생성자 메소드를 정의할 때 부모클래스의 생성자메소드를 호출하려는 super() 메소드를
      반드시 사용해야 한다.
    • 오류 정보에 필요한 멤버변수를 추가할 수 있다.

  • 작성 목적
    • 애플리케이션에 최적화된 예외를 정의할 수 있다. (자바에서 제공해주는 것과 달리)
    • 애플리케이션에서 발생하는 예외의 종류를 단순화시킬 수 있다.
      (지정하고자 하는 사용자정의 예외클래스 타입으로 통일시켜 발생시킬 수 있으므로)
    • 예외의 종류를 단순화시킬 수 있기 때문에 최종단계에서 예외에 대한 일괄처리가 단순해진다.
    • 다양한 오류정보를 표현할 수 있다.
      • 오류에 대한 더 정확한 내용을 전달할 수 있다. 문법적인 문제 뿐만이 아니라, 업무 로직상의 문제 또한 메세지에 내용을 적어 예외로 발생시킬 수 있다.
      • 예외의 처리는 한 곳에서 일괄적으로 할 것이기 때문에 처리를 하는 것보다 적절한 예외를 발생시키는 것이 더 중요하다.
    public class HtaException extends RuntimeException {
    
    	private static final long serialVersionUID = 9175601348921699186L;
    
    	public HtaException(String message) {
    		super(message);
    	}
    	
    	public HtaException(String message, Throwable cause) {
    		super(message, cause);
    	}
    }

💡 serialVersionUID
Serializable 인터페이스의 구현 클래스에는 serialVersionUID가 정의되어있어야 한다. 없다고 컴파일 에러가 생기지는 않지만, 이는 클래스의 식별번호로서 네트워크로 객체를 주고받을 때 주로 사용된다.

  • 정의하는 목적
    1. 설계도에 대한 빠른 식별
    2. 다시 컴파일하더라도 식별번호가 달라지지 않도록 해서 같은 설계도를 다른 것으로 인식하지 않도록 함.

💡 예외클래스 생성의 의미
Exception 클래스는
- String값을 받아서 메시지로 저장하는 생성자
- Throwable 구현 객체를 받아서 원인이 되는 예외를 저장하는 생성자 를 가지고 있다.
Exception 또는 RuntimeException 클래스를 상속받은 사용자정의 예외클래스 또한 자바 라이브러리의 다른 예외클래스처럼
메시지와 원인이 되는 예외 객체를 저장할 수 있게 하기 위하여 정의한다.
이 생성 과정을 통해 예외의 내용이 정해지는 것이 아니다.
이는 기본적으로 예외 객체를 만들고, 내용을 저장해 사용할 수 있도록 하는 클래스의 생성 방법이다.


📌 강제 예외발생

  • 업무로직상의 오류가 있는 경우(비밀번호 불일치, 잔액부족, 로그인 실패 등) 예외를 강제로 발생시켜서 해당 기능을 호출한 측에게 오류가 발생했음을 알리는 것이다.
  • throw 키워드를 사용한다.
  • throw로 발생시킨 Unchecked 예외객체는 따로 처리하지 않으면 다음의 호출하는 주체로 위임된다. (처리가 강제되지는 않고, 떠넘겨지는 것이다.)


📌 예외의 변환

  • 실제 발생한 예외 대신 사용자정의 예외를 발생시키는 것
  • throw 키워드를 사용한다.
  • throw new 예외클래스(오류메세지, 실제발생한예외)
    • 사용자 정의 예외객체와 실제 발생한 예외(원인이 된 예외=cause)객체에 대한 정보가 모두 출력된다.
  • 여러 종류의 예외를 처리하는 것보다 하나의 사용자정의 예외만 처리하도록 하는 것이 목적이다.
    • 예외의 종류 단순화
    • 어떤 부분에서 에러가 났는지 파악하기 쉬워진다.
    • 메소드에서 발생하는 다양한 예외를 catch블록에서 잡고, 대신 사용자정의 예외를 발생시킬 수 있다.
      • 또다시 사용자정의 예외는 처리할 필요가 없도록 unchecked로 작성한다.
      • cause 인자값을 통해 실제 발생한 예외에 대한 정보를 전달할 수 있다.
      • 사용자정의 예외 클래스를 부모 클래스와 여러 자식 클래스로 나누어, catch는 부모 클래스로-하나의 사용자정의 예외클래스 타입으로- 정의하고 throw문에서는 자식 클래스들을 이용해 경우별로 구체적으로 나눌 수 있다.

💡 예외의 변환
사용자정의 예외클래스는 unchecked로 한다. checked라면 또 이 클래스에서 예외처리를 해야 하므로. 여러 예외를 같은 ‘사용자정의 예외클래스’로 묶어서 전달시키는 것이 목적이다.

try {
    예외발생이 예상되는 코드 // SQLException 이 발생예상됨
  } catch (SQLException e) {
    throw new 사용자정의예외클래스("메세지", e);
  }
public class CommonUtils {

	public static int stringToInt(String text) {
		if (text == null) {
			// 사용자 정의 예외객체 발생시키기
			throw new HtaException("text는 null일 수 없습니다.");
		}
		if (text.isBlank()) {
			// 사용자 정의 예외객체 발생시키기
			throw new HtaException("Text가 빈 문자열이거나 공백문자입니다.");
		}
		try {
			int value = Integer.parseInt(text);
			return value;
		} catch (NumberFormatException ex) {
			// 예외의 변환
			// Integer.parseInt()메소드가 발생시킨 NumberFormatException을 catch에서 잡고, 대신 HtaException을 발생시키기
			throw new HtaException("text에 숫자가 아닌 문자가 포함되어 있습니다.", ex);
		}
	}
	
}

💡 예외를 발생시키는 것 자체가 메소드 블록 내의 ‘빠른 종료’를 시킨다.
따라서 값을 반환하는 메소드에서 값 반환 대신 예외를 발생시켜도 컴파일 오류는 아니다.
그러나 if문 내에서 예외를 발생시킨다면, if문이 false일 경우-반환값이 없을 경우-도 고려해야 한다.
(if문 내에서 예외 발생, if문 밖에서 아무것도 반환하지 않는다면 오류)


📌 계층적 프로그래밍에서의 예외 발생

어플리케이션 개발 시 표현계층 / 서비스계층 / 영속화계층
세 계층으로 나누어 개발하는데,

업무로직을 수행하는 서비스계층(Service 클래스)에서 수행과정 중 업무로직에 위배되는 상황이 발생하면 예외를 발생시킨다.
영속화계층(DAO클래스, Repository클래스)는 특별한 업무로직을 수행하지 않고 업무로직 수행에 필요한 데이터엑세스 작업을 지원한다.

발생한 예외는 최종적인 위치인 표현 계층(Controller 클래스) 에서 일괄적으로 처리한다. 그 전까지는 계속해서 위임시킨다.

0개의 댓글