본문 바로가기

프로그래밍/기타

Exception

Exception (예외상황)

오류 : 프로그램이 정상적으로 수행이 안되는 상황 <실행시에 발생하는 것>
         Throwable 클래스를 상속 받음. (Exception, Error)
  1. Error : 심각한 오류. 처리할 수가 없음.
               하드웨어적인 오류가 많음.
  2. Exception : mild한 오류. 소프트웨어적인 오류.
                      오류 발생시 처리 가능. → Exception Handling
                     


Exception
1. Checked Exception
    반드시 처리해줘야 할 Exception을 처리하지 않았을 때, 컴파일 시에 점검해주는 오류.
    프로그램 자체의 문제가 아니라, 실행 환경상 발생하는 문제.
    프로그램 개발 시 발생 여부 예측 불가능.
    반드시 Exception Handling 이 필요.

2. Unchecked Exception
    프로그램 자체의 문제(잘못 작성)
    실행 시 100% 발생
    Handling보다 프로그램을 수정하는 것이 맞다.



예외 처리 : try, catch , finally, thorws
예외 발생 : throw

Call Stack 메커니즘으로 그 오류를 발생시킨 곳으로 따라감. 최종적으로 JVM이 처리를 하게됨.




try{
      Exception이 발생할 가능성이 있는 code.
      예외 발생 시, 오류객체 생성
}catch(오류객체타입 오류객체)
{
      Handling 코드
}



◇ 실행 순서
try{
    1:
    2: 오류발생
    3:
    4:
}catch(   ){
    5:
}
    6:

1→2→5→6  [5번라인에서 오류처리시]
1→2→5→종료 [5번라인에서 오류 미처리시]


◇ 계층적 Exception
    A_Exception / B_Exception extends A_Exception / C_Exception extends B_Exception 인 경우


     try{
    1: AE 발생                  
    2: BE 발생
    3: CE 발생
    4: DE 발생
}catch(AE a ){
    5:
}catch(BE a ){
    6:
}catch(CE a ){
    7:
}
    8:

   1,2,3의 경우에 어떠한 Exception이 발생할 경우에도 다 5번에서 처리를 하고 끝이남.
   상속의 계층성에 의해서 AE에서 하위객체인 BE와 CE모두 처리가 가능. 따라서 예외가 이처럼
   계층적으로 되어 있을 경우에는,

     try{
    1: AE 발생                  
    2: BE 발생
    3: CE 발생
    4: DE 발생
}catch(CE a ){
    5:
}catch(BE a ){
    6:
}catch(AE a ){
    7:
}
    8:
   
   이렇게 역 계층적으로 예외를 처리해주어야 올바르게 처리를 할 수 있다.
   하지만, 이러한 경우에도 DE을 처리할 수가 없다. 그렇다면 8번은 DE 발생 시 처리가 불가능하다.
   외부의 자원을 사용할 경우에 만약 8번 라인이 그것을 해제하는 부분이라면, 문제가 발생할 수 있다.
   그래서, 무조건적으로 처리를 해야되는 구문이 있다면,(예외의 처리 여부를 떠나서) 다음과 같이
   finally를 써서 작성한다.

     try{
    1: AE 발생                  
    2: BE 발생
    3: CE 발생
    4: DE 발생
}catch(CE a ){
    5:
}catch(BE a ){
    6:
}catch(AE a ){
    7:
}finally{
    8:  // 무조건 처리.
}


◇ API에 있는 메소드 중에 throws 하는 메소드 사용 시에는 반드시 try~catch로 예외처리를 해주어야함.
    해당 throws에 맞는 예외를 처리.

   ex) java.lang.Thread 에 Sleep API
         sleep
              -  public static void sleep(long millis)    throws InterruptedException 

반드시 try~catch를 해주지 않으면 컴파일 에러가 발생한다.



◇ 함수 호출 시 예외처리


void CallMethod()
{
     try{
      TE.testException();   // testException 에서 예외가 발생 가능성이 있다는 것은
                                    // 호출하는 메서드에서도 발생 가능성이 있다는 것을 말함.
                                    // 따라서 호출해서 처리되는 곳에서 예외처리를 안하면
                                    // 호출시킨 곳에서 예외 처리를 해주어야 함.
    } catch(AE e1) {
 
    } catch(BE e2) {

    }
 }
}

void testException() throws AE,BE{
     // 익셉션 발생 가능 코드
     // 이 곳에서 예외 처리를 하는 것이 아니라, call stack 메커니즘에 의해서 이 메소드를 호출한
     // 곳으로 보내서 예외를 처리. 어떠한 예외인지 알려주기 위해서
     // 메소드 선언 시에 throws를 이용해서 발생 가능한 예외를 사전에 미리 알려줘야 함.
     // 만약 이 메소드에서 try{} catch{}를 해서 바로 예외를 처리해주면, throws 안 씀.
}


◇ Exception 클래스 만들기
   public class 만들고자하는Exception명  extends  상속받을상위Exception  {
             Default생성자() {}                                   // 반드시 필요한 것은 아니나
             생성자(String msg) { return super(msg) }  // 일반적으로 필요에 의해서 만드는 최소한의 메소드
   }

  Ex]  public class PlmingException  extends  Exception  {
             PlmingException() {}
             PlmingException(String msg) { return super(msg) }
   }


◇ 사용자 Exception 발생시키기

   public class PlmingException  extends  Exception  {
             PlmingException() {}
             PlmingException(String msg) { return super(msg) }
   }

 public void catchExcetpion()
 {
          try{
             TestException();
          }catch(PlmingException pe){
               Stinrg str = pe.getMessage();
               System.out.prinln(str); //생성자로 넣어준 문자열을 출력
          }
 }

 public void TestException() throws PlmingException{
    PlmingException PE = new PlmingException("문제점");  // 생성자로 문자열을 넣어준다.
    throw PE;
}



◇ printStackTrace()
  Exception이 발생한 경로를 출력해주는 것.



◇ Exception Overrding
  1. return type, argment list
  2. access modifier
  3. exception → 부모 것이 throws 한 것만 throws 할 수 있다. ( throws 하지 않아도 됨.)
                    → 개수는 상관없다.
                    → 부모가 던진 것을 하위 Exception에서 던질 수 있다.


   AE
  ↑  ↑
BE  CE
 ↑
DE

  ▷ public void go throws AE{ }
     
      public void go throws BE, CE, DE { }    - 가  능 : 부모의 throws를 상속받은 것을 써도 됨. 개수 상관없음.


  ▷ public void go throws AE{ }
     
      public void go{}                                 - 가  능 : 부모의 throws를 안 받아도 상관없음.

      public void go throws BE, CE, DE { }   - 불가능 : 바로 상위 클래스에서는 throws를 안했으므로.