예외 처리

이한수·2022년 3월 12일
0

JAVA

목록 보기
5/9

개인 공부 정리 목적입니다.
잘못된 부분이 있을경우 알려주시면 감사하겠습니다.

프로그램 오류란 프로그램이 실행 중 어떤 원인에 의해서 오작동을 하거나 비정상적으로 종료되는 경우를 의미한다.
이를 발생 시점에 따라 "컴파일 에러"와 "런타임 에러"로 분류할 수 있다.
이외에도 "논리적 에러"가 있다.

컴파일 에러

  • 컴파일단계에서 오타 혹은 잘못된 구문 , 자료형 체크 등의 기본적인 검사를 수행하여 오류가 있는지를 알려준다.
    컴파일 단계에서 확인되는 오류로써 정말 감사한 오류라고 볼 수 있다.

런타임 에러

  • 실행 도중에 발생하는 오류로써 , "에러"와 "예외" 2가지로 구분할 수 있다.
    • 에러의 경우 메모리 부족이나 스택오버플로우와 같이 발생하더라도
      프로그램 코드에 의해 수습이 불가하다.
    • 예외의 경우 프로그램 코드에 의해 수습이 될 수 있다.

예외 클래스 계층 구조

위 사진 중에서도 파란색 테두리로 칠해진 부분이 예외 클래스 부분이다.
보면 알다시피 최상위 클래스는 Exception클래스이다.

또 그 예외들 중에서 2가지로 나눌 수 있는데 ,

  • Exception클래스와 그 자손들
  • 또 한가지는 RuntimeException클래스와 그 자손들로 나눌 수 있다.

RuntimeException클래스의 경우 프로그래머의 실수에 의해 발생될 수 있는 예외들이다.
예를들어 ArrayIndexOutOfBoundsException , NullPointException등을 예시로 들 수 있다.

그 외의 클래스들은
외부의 영향으로 발생할 수 있는 것들 로써 사용자들의 동작에 의해서 발생하는 경우가 많다.
예를 들어 FileNotFoundException , ClassNotFouneException 등을 예시로 들 수 있다.

이와 같은 예외들을 만났을 경우 프로그램은 동작하다가 정지해버린다.
실제 서비스를 제공하고 있다고 가정할 시에 매우 치명적이다.
에러와 같은 경우는 어쩔 수 없지만 예외는 다행히도 프로그래머가 조치를 취할 수 있으므로 다음 구문부터 알아보자.

Try ~ catch

  • 프로그램 실행 시 발생할 수 있는 예기치 못한 예외의 발생에 대비한 코드를 작성하는 것으로써 ,
    예외가 터지더라도 비정상적인 종료를 막고 정상적인 실행상태를 유지할 수 있게끔 해준다.

    만일 발생된 예외를 처리하지 못할 경우 프로그램은 비정상 종료되고 ,
    JVM의 예외처리기가 받아서 예외의 원인을 화면에 출력한다고 한다.
    또한 , RuntimeException쪽 예외는 try~catch문을 처리해주지 않아도 컴파일은 되지만,
    그 외에 처리들은 try~catch문등을 이용하여 예외처리를 해주지 않으면 컴파일 조차 되지 않는다.

    try{
    //예외가 발생할 수 있는 구문
    }catch(Exception e){
    //예외가 발생할 경우 처리하기 위한 문장.
    }

catch문은 여러개가 올 수 있으며 발생한 예외의 종류와 일치하는 catch문만 실행된다.
만일 발생하지 않을 경우 try문만 수행하고 전체 try~catch문을 빠져나가 수행을 계속한다.

또한 모든 예외 클래스는 Exception클래스를 상속받았으므로 catch문에서 Exception으로 작성을 해주면 어떤 종류의 예외가 발생하더라도 잡을 수 있다.
단 , Exception은 다중 catch문이 있을 경우 맨마지막에 적어주어야 한다.

printStackTrace와 getMessage

  • 보통 catch문 내에 이 2개의 메소드를 적어주는 편인데,
    살펴보자면 ,
    printStackTrace는 예외 발생 당신의 호출스택에 있던 메서드의 정보와 예외 메세지를 화면에 출력한다.
    getMessage는 발생한 예외 클래스의 인스턴으세 저장된 메세지를 얻을 수 있다.

이것을 사용함으로써 , 예외가 발생했을 경우 발생원인의 파악과 어디서 발생되었는지를 확인할 수 있다.

예외 직접 발생시키기 : throw 예약어를 사용한다.

예외 선언

try~catch문 이외에 예외를 메서드에 선언하는 방법이 있다.

void exTestMethod() throws Exception { 메소드 내용}

이와 같은 형태로 throws를 이용하여 선언할 수 있다.
여러개일 경우 , 로 구분하여 작성해주면 된다.
이렇게 사용하면 좋은 것이 상속관계를 고려해볼 경우 이 메소드를 오버라이딩 할 떄 ,
메소드만 보고 호출하는 쪽에서 어느 예외처리를 해주면 될것인지 알 수 있다는 장점이 있다.

finally블럭

  • 예외의 발생여부에 상관없이 실행되어야할 코드를 포함시킬 목적으로 사용된다.
    예외 발생 경우 : try -> catch -> finally
    예외가 아닐 경우 : try -> finally

보통 자원을 해제하는 경우에 자주 썻던것으로 기억한다.
자원을 할당받아 사용중이지만 중간에 오류가 발생하여 예외처리가 될 경우 try문안에 자원해제 문까지 같이 적어놨을 경우 그 구문은 수행이 안되고 catch문으로 넘어가게 된다.
이렇게 될 경우를 대비하여 예외가 발생하던 아니던간에 사용후에는 해제될 수 있게끔 finally문안에 작성해놓고는 한다.

보통 입출력 관련해서 사용할때를 예시로 들 수 있다.
InputStream을 사용할 경우 close메소드로 닫아 주는 경우를 예시로 들 수 있다.

근데 한가지더 문제점이 있다..
이 close메소드도 예외를 발생시킬 수 있다는 점이다.
그래서 보통 finally 구문안에 try문을 사용하여 close에 대한 예외처리를 하는데 , 사실 듣기만해도
매우 귀찮아 지는 작업이라고 생각한다.

고로 이를 위해 태어난 방법이
try ~ with ~ resource 문이라고 할 수 있다.

try( FileInputStream fis = FileInputStream("파일");
DataInputStream dis = new DataInputStream(fis))

위와 같이 try옆에 사용하고자 하는 객체를 넣으면 close를 호출할 필요없이 try구문을 벗어나는 순간
자동적으로 close가 호출된다.
그 다음에 catch 혹은 finally문이 수행된다.

근데 이것또한 !! 주의할 것이 있으니 ...
바로 close가 호출될 클래스는 반드시 AutoCloseable 인터페이스를 구현한 것이어야만 한다.

profile
성실하게

0개의 댓글