ch14 : 예외

목차

try-catch 구문

try () {

} catch (Exception e) {

} finally {

}

참고로 오류 출력할 때는 System.out.println() 이것보다 System.err.println() 을 사용하는 것이 좋음! (IDE에서 다른 색으로 표시됨)

  • try 구문에서 오류 발생시

    • 예외 발생 이후 문장은 처리하지 않고 catch구문으로 이동함

  • 변수 범위!

    • try 블록 안에서 선언한 변수는 catch블록에서 사용할 수 없다.

    • 보통 catch 문장에서 사용할 변수는 try 앞에 미리 선언하여 사용한다.

  • finally 블록

    • try-cath 구문 이후에 예외발생여부와 상관없이 실행되는 블록

    • 코드의 중복을 피하기 위해 반드시 필요하다.

  • catch 블록

    • catch 블록은 여러 개를 사용할 수 있다. 단, 이때는 catch 블록들의 순서가 중요하다.

    • 먼저 선언한 catch 블록에서 예외가 잡히면, 다음 블록은 pass한다.

    • 이때, 먼저 선언된 catch 블록이 이후 선언된 catch 블록의 부모 예외 클래스면, 컴파일 에러가 발생한다. (이후 선언된 catch 블록은 의미가 없으므로)

      // 이럴 경우 컴파일 에러가 난다
      try () {
      
      } catch (Exception e) { // 부모
      
      } catch (NullpointerException e) { // 자식, 이 구조면 여기서 에러 catch할 일이 없음
      
      }
    • 모든 예외의 부모 클래스는 java.lang.Exception 클래스다. 또한, 발생한 예외가 catch 블록에 해당하지 않으면 예외가 발생하면서 스레드가 종료된다.

      • 따라서 Exception을 가장 마지막 catch 블록에 배치하여 안전한 프로그램을 만드는 것이 좋다.

예외의 종류

종류

  1. error

  2. Runtime exception (unchecked exception)

  3. checked exception

  • Error

    • 자바 프로그램 밖에서 발생한 경우 (디스크 고장 등)→ 개발자가 신경 쓸 필요X

    • Error는 프로세스에 영향을 주고, Exception은 쓰레드에만 영향을 준다.

    • ex) OutOfMemoryError, ThreadDeath, StackOverflowError

  • Runtime exception (런타임 예외), Unchecked exception라고도 함

    • Runtime 시점에 발생하는 예외로, 프로그램을 실행할 때(컴파일 시) 체크해주지 않아도 되는 예외들

    • 이 경우 따로 에러 처리(try/catch or throw)를 하지 않는다. 예외 처리를 직접 하기보다는 예외가 발생하지 않도록 프로그래머가 주의해야 한다.

    • 컴파일시에 체크하지 않고, 실행시에 발생하는 예외이므로 unchecked exception이라고도 한다.

    • Runtime Exception을 확장한 예외들이다.

    • ex) ArrayIndexOutOfBoundsException, NullPointerException

  • Checked exception

    • Runtime 시점에 발생하지 않고 Compile 시점에 발생해서 무조건 체크해야하는 예외들

    • 반드시 에러 처리(try/catch or throw)를 해야하는 경우

    • Exception을 바로 확장한 예외들이다.

    • ex) FileNotFoundException, ClassNotFoundException

❔Unchecked exception VS Checked exception ?

Checked exception는 정상적인 프로그램에서 일반적으로 발생할 수 있는 예외사항이지만, (ex. 사용자가 파일명을 잘못 입력한 경우) Unchecked exception는 프로그램 설계의 잘못으로 발생하는 버그가 대부분이다. (ex. 개발자의 코드 누락)

일반적으로 사용자가 프로그램 사용중에 만드는 exception들은 Checked exception에 해당한다. 예를 들어, 사용자가 존재하지 않은 파일을 호출할 경우 FileNotFoundException이 발생하고, 이때는 에러 처리(try/catch or throw)를 통해 다시 입력하라는 메세지를 전달해줄 수 있다. 참고 링크

반면, 만약 개발자가 '사용자가 입력한 파일명'을 통해 어떤 메소드에 접근하는 코드를 작성해야하는데, 파일명을 가져오는 코드를 누락해서 null에 접근해서 메소드를 호출할 경우는 Unchecked exception이다. 이는 에러처리가 아니라 에러가 발생하지 않도록 코드 누락이 없게 개발자가 주의해야 한다. 참고 링크2

이론적으로는 위와 같지만, Checked Exception을 Unchecked Exception으로 throw하는 게 좋다.

Throwable

  • 모든 예외(Exception 혹은 Error)는 Throwable클래스를 상속받는다.

  • 따라서 Exception이나 Error를 Throwable로 처리해도 된다.

  • Throwable()

    • Throwable()

    • Throwable(String message) 예외 메세지 전달

    • Throwable(Throwable cause) 예외 원인을 전달

  • Throwable에 선언된, 그리고 Exception 클래스에서 오버라이딩된 메소드들

    • getMessage() : 예외 메세지를 String 형태로 받는다. 어떤 예외가 발생했는 지 확인할 떄 사용한다.

      • ex) 예외.getMessage(); // null 출력

    • toString(): getMessage보다 더 자세하게, 예외 클래스명도 확인할 수 있다.

      • ex) 예외.toString(); // java.lang.NullPointerException 출력

    • printStackTrace() : 첫 줄에 예외 메세지를 출력하고, 두번째부터는 예외가 발생하게 된 메서드들의 호출 관계(스택 트레이스)를 출력한다. (다만 로그가 많이 쌓이므로 개발 시에만 사용할 것)

throws

  1. throw : 예외 발생시키기

    • try-catch 블록에서 사용하는 방법

      • 이때 throw한 예외 클래스가 catch 블록에 없으면 컴파일 에러가 발생한다.

    • throws와 같이 사용(메소드 밖으로)

      • 이떄 throw한 예외 클래스가 해당 메소드의 throws 선언 뒤에 없으면 컴파일 에러가 발생한다.

        public void throwsException(int num) throws Exception {
        	if (num > 12) {
        		throw new Exception("nope");
        }
  2. throws : 메소드 밖으로 보내기 (처리 위임)

    • 해당 메소드를 호출한 메소드에게 예외 전달함

    • 이때 호출한 메서드에서는 반드시 해당 예외를 try-catch 블록으로 처리해야 한다.

    • 두가지 이상의 예외를 던질 경우, 콤마로 구분하여 적어줄 것

      public void multiException() throws NullPointException, Exception {
      	//
  • throws를 선언한 매서드를 호출한 메서드 쪽에선 이 호출한 메서드를 반드시 try-catch블럭으로 감싸야 한다.

  • 예외를 throw하는 이유는 해당 메서드에서 예외를 처리하지 못하는 상황이거나, 미처 처리하지 못한 예외가 있을 경우 대비하기 위함이다.

  • 단, throws한걸 또 throws하는건 좋지 않다. throws 하는 메서드를 호출하는 쪽에서 try-catch로 처리하는 것이 가장 좋다.

예외 만들기

  • Exception 예외 만들기

    • Throwable 혹은 Throwable의 자식 클래스(Exception 등)의 상속을 받아야 한다.

    • ex)

      package c.exception;
      
      // 내가 만든 예외 클래스
      public class MyException (int number) extends Exception { // 꼭 상속받아야 예외 클래스로 인정해줌, 안 할경우 컴파일 에러가 난다.
      		public MyException() {
      			super();
      		}
      
      		public MyException(String message) {
      			super(message);
      		}
      	}
      
      // 테스트
      public class CustomException {
      
      	public static void main(String args[]) {
      		CustomException sample = new CustomException();
      		try {
      			sample.throwMyException(13); // 여기서 던짐
      		} catch (MyException mye) {    // catch
      			mye.printStackTree();
      		}
      	}
      
      	public class throwMyException (int number) throws MyException { 
      		try {
      			if (number > 12) {
      				throw new MyException("over 12");
      			}
      		} catch (MyException e) {
      			e.printStackTree();
      		}
      	}
      }

자바의 예외 처리 전략

  • 실행 시에 발생할 확률이 높은 경우, 런타임 에러로 만드는 것이 좋을 수 있다 (extends RuntimeException) ⇒>>???

  • 'java exception strategy' 검색하여 참고할 것

Last updated