ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 학원 DAY25~26. 예외 처리(2)
    기록 2022. 10. 12. 00:07

    예외처리방법1. try-catch

    catch (ParseException ex) { // ()안에는 실제로 발생하는 예외타입 또는 그 부모의 예외타입을 적어도 된다.

        System.out.println("### 가로챈 예외 : " + ex); // 참조변수를 출력하게 되면 패키지를 포함한 예외클래스의 이름과 예외의 원인이 출력된다.

     

    예외처리방법2. throws

    throws는 예외의 위임.

    메소드4에서 발생한 예외를 호출한 측(메소드2)으로 예외를 던짐.

    마찬가지로 메소드2에서도 발생한 예외와 메소드4로부터 떠맡겨진 예외를 메소드2를 호출한 측으로 던진다.

     

    void method1() throws xxxException { //checkedExceptionxxxException의 발생이 예상되는 수행문}

    * 발생이 예상되는 예외가 checkedException인 경우, 반드시 try-catch문을 사용해서 직접 예외처리를 하던지 혹은 throws를 사용해서 예외처리를 위임할 것인지 정의해야 한다.

     

    void method2() { //uncheckedExceptionyyyException의 발생이 예상되는 수행문}

    * 발생이 예상되는 예외가 uncheckedException이면 예외처리를 하지 않아도 된다.

    try-catch를 사용해서 직접 예외처리를 할 수 있다.

    예외처리를 위임시킬 때는 throws를 사용하지 않아도 이 메소드에서 발생한 예외가 이 메소드를 호출한 측에게 자동으로 예외가 전달되고, 예외처리가 위임된다.

     


    Throwable 클래스

    - Error, Exception의 부모 클래스

    - 오류와 관련된 모든 메소드들이 구현되어 있다.

    - 모든 Error, Exception클래스는 Throwable에 구현된 메소드를 상속받고, 사용할 수 있다.

    - 특별한 경우가 아니면, 사용자정의 예외클래스를 정의할 때 생성자만 정의해도 된다.

    public class Throwable
    
    String message; // 오류 메시지를 저장하는 변수
    Throwable cause; // 오리지널 오류 객체를 저장하는 변수
    
    // 생성자 메소드
    public Throwable(){}
    
    public Throwable(String message){
    	this.message = message;
    }
    
    public Throwable(Throwable cause) { 
    	this.cause = cause;
    }
    
    public Throwable (String message, Throwable cause) { 
    	this.message = message;
    	this.cause = cause;
    }
    
    // 멤버메소드
    public String getMessage(){
     return message;
    }
    
    public void printStackTrace() { 
      // 디버깅에 필요한 오류정보를 출력한다.
    }

    - 주요 생성자

    public Throwable() { ... }

    : 기본생성자

    public Throwable(String message) { ... }

    : 오류와 관련된 메세지를 전달받는 생성자

    public Throwable(String message, Throwable cause) { ... }

    : 오류와 관련된 메세지 및 오류의 원인이 되었던 이전 예외객체를 전달받는 생성자

    public Throwable(Throwable cause) { ... }

    : 오류의 원인이 되었던 이전 예외객체를 전달받는 생성자

     

    - 주요 메소드

    Throwable getCouse()

    : 오류발생의 원인이 되었던 오류를 반환한다.

    String getMessage()

    : 오류와 관련된 상세한 메세지를 반환한다.

    void printStackTrace()

    : 오류 발생과 관련되어서 실행되었던 코드를 화면에 출력한다. 오류검출을 위한 디버깅 작업에서 참조한다.

    void printStackTrace(PrintStream s)

    : 오류 발생과 관련되어서 실행되었던 코드를 화면이 아닌 다른 곳에 출력하게 할 수 있다.

    void printStackTrace(PrintWriter s)

    : 오류 발생과 관련되어서 실행되었던 코드를 화면이 아닌 다른 곳에 출력하게 할 수 있다.

     

    +)

    Exception 클래스 ->  Throwable 클래스를 상속받음, 생성자 밖에 없음.

    Exception클래스를 상속받은 IOException 또한 생성자 밖에 없다.

    대부분의 예외클래스는 거의 생성자 밖에 없다.

    super 생성자를 통해 부모인 Throwable클래스의 오류를 저장하는 변수에 오류를 담는다.

    실질적인 멤버메소드는 Throwable클래스에서만 갖고 있다.

    package day26;
    
    public class ExceptionApp2 {
    	
    	public static void main(String[] args) {
    		
    		// 예외 객체의 주요 메소드 사용하기
    		try {
    			int number = Integer.parseInt("1234A");
    			System.out.println(number);
    		} catch (Exception ex) {
    			// 오류 메세지 조회
    			String errorMessage = ex.getMessage();
    			System.err.println("오류 메세지: " + errorMessage);
    			
    			// 디버깅에 필요한 정보 출력하기
    			System.out.println("### 디버깅에 필요한 정보 출력하기");
    			ex.printStackTrace();
    		}
    	}
    }
    
    
    출력 결과
    오류 메세지: For input string: "1234A"
    ### 디버깅에 필요한 정보 출력하기
    java.lang.NumberFormatException: For input string: "1234A"
    	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
    	at java.base/java.lang.Integer.parseInt(Integer.java:668)
    	at java.base/java.lang.Integer.parseInt(Integer.java:786)
    	at day26.ExceptionApp2.main(ExceptionApp2.java:9)

    예외가 발생했는데 예외처리를 안하면 자바가상머신은 자신이 전달받은 예외객체의 printStackTrace를 실행하고 종료한다. printStackTrace는 디버깅에 필요한 정보를 담고 있다.


    강제 예외 발생

    • 업무로직상의 오류가 있는 경우(비밀번호 불일치, 잔액부족, 로그인 실패 등) 예외를 강제로 발생시켜서 해당 기능을 호출한 측에게 오류가 발생했음을 알리는 것이다.
    • 예외 객체를 만들어 오류상황에 대한 더 많은 정보를 제공할 수 있다.
    • throw 키워드를 사용한다.
     public void login(String id, String password) {
        User savedUser = userService.getUser(id);
        if (savedUser == null) {
          throw new UserNotFoundException("아이디가 존재하지 않습니다.");
        }
        if (!savedUser.getPasswrd.equals(password)) {
          throw new NotMatchedPasswordException("비밀번호가 일치하지 않습니다.");
        }
        ...
      }

     < throws와 throw >


    throws는 예외처리 위임
    public void method() throws 예외1, 예외2 {
        예외1과 예외2가 발생되는 수행문들;   // 예외를 직접 처리하지 않고 예외처리를 위임하기 위해서 throws 사용

    }


    throw는 예외 강제 발생  ( 메소드 안에서 사용 ) 
    public void method(int score) { 
          if (score < 0) {    // 점수는 절대로 음수가 될 수 없다. 이 조건이 true로 판정되는 경우는 잘못된 경우다.
               throw new 예외클래스("오류메세지 : 올바른 점수가 아닙니다.");   // 예외 강제발생
           }          
    }

    * 강제로 발생시키는 예외는 자바에서 제공하는 예외클래스 혹은 사용자정의 예외클래스로 예외객체를 생성할 수 있다.


    사용자 정의 예외클래스

    Checked 예외클래스 만들기

    - Exception 클래스를 상속받아서 사용자정의 예외 클래스를 만든다.

     

    Unchecked 예외클래스 만들기

    - RuntimeException 클래스를 상속받아서 사용자정의 예외 클래스를 만든다.

    - 현재는 대부분 Unchecked 사용자정의 예외클래스를 선호합니다.

     

    사용자정의 예외클래스 정의하기

      public class MyException extends RuntimeException {
        public MyException() {}
        public MyException(String message) {
          super(message);
        }
        public MyException(String message, Throwable cause) {
          super(message, cause);
        }
        public MyException(Throwable cause) {
          super(cause);
        }
      }

    - Throwable클래스가 에러메세지, 관련 예외를 저장하는 멤버변수를 가지고 있고 초기화하는 생성자도 보유하고 있기 때문에, 부모의 생성자를 통해서 객체를 초기화한다

    - 사용자 정의 Exception을 만들 때 super()를 가장 많이 사용한다.

     

     * 사용자 정의 예외클래스를 정의하는 목적 
      - 개발하는 애플리케이션에 대한 오류 정보를 표현하는 예외 클래스를 정의하기 위해서다. 
      - 개발하는 애플리케이션에서 발생하는 다양한 예외를 사용자정의 예외로 변환해서 예외처리를 단순화한다.

     

    예외의 변환

    - 실제 발생한 예외 대신 사용자정의 예외를 발생시키는 것

    - throw 키워드를 사용한다.

    - throw new 예외클래스(오류메세지, 실제발생한예외)

    - 여러 종류의 예외를 처리하는 것보다 사용자정의 예외만 처리하도록 하는 것이 목적이다.

     

    예외처리 변환하기 

      try {
        예외발생이 예상되는 코드 // SQLException 이 발생예상됨
      } catch (SQLException e) {
        throw new 사용자정의예외클래스("메세지", e);
      }
    public class CustomExceptionApp1 {
    
    	public static void main(String[] args) {
    		int result3 = CustomExceptionApp1.textToInt("1234");
    		System.out.println("정수값: " + result3);
    		int result4 = CustomExceptionApp1.textToInt("1234a");
    		System.out.println("정수값: " + result4);
    	}
    
    	// NumberFormatException -> CustomUncheckedException 발생 가능성이 있는 메소드
    	public static int textToInt(String text) {
    		try {
    			return Integer.parseInt(text);
    		} catch (NumberFormatException cause) {
    			throw new CustomUncheckedException("숫자가 아닌 문자가 포함되어 있습니다.", cause);
    		}
    	}
        
        
    출력 결과
    정수값: 1234
    Exception in thread "main" day26.CustomUncheckedException: 숫자가 아닌 문자가 포함되어 있습니다.
    	at day25.CustomExceptionApp1.textToInt(CustomExceptionApp1.java:45)
    	at day25.CustomExceptionApp1.main(CustomExceptionApp1.java:22)
    Caused by: java.lang.NumberFormatException: For input string: "1234a"
    	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
    	at java.base/java.lang.Integer.parseInt(Integer.java:668)
    	at java.base/java.lang.Integer.parseInt(Integer.java:786)
    	at day25.CustomExceptionApp1.textToInt(CustomExceptionApp1.java:43)
    	... 1 more

    * 사용자정의 예외를 만들 때 UncheckedException으로 만드는 이유는? 

    예외처리 안하고 넘기는 것이 편하기 때문에. 만약 CheckedException을 쓴다면, 다 throws를 적어줘야 하기 때문에 귀찮음. 

     

    * 일괄 예외 처리시 장점

    예외를 강제 발생시켜서 예외에 대한 정보를 적고, 업무로직 코딩하는 것에만 집중할 수 있다.

    '기록' 카테고리의 다른 글

    학원 DAY28. SQL  (0) 2022.10.15
    학원 DAY27. 데이터베이스, SQL  (0) 2022.10.15
    메소드 작성 관련  (0) 2022.10.08
    학원 DAY24. 맵 활용하기  (0) 2022.10.08
    학원 DAY24. 예외 처리  (0) 2022.10.08

    댓글

Designed by Tistory.