[JAVA] 예외처리

Coastby·2022년 9월 29일
0

LIKELION Back-End School

목록 보기
23/61
post-custom-banner

○ 프로그램 오류

프로그램이 실행 중 어떤 원인에 의해 오작동하거나 종료되는 것은 에러 또는 오류라고 한다.
발생 시점에 따라 '컴파일 에러 (compile-time error)', '런타임 에러 (runtime error)'로 나눌 수 있다. 컴파일도 잘 되고 실행도 잘 되지만 의도한 것과 다르게 도작하는 것을 '논리적 에러 (logical error)'라고 한다.

소스코드를 컴파일하며 컴파일러가 소스코드에 대해 오타나 잘못된 구문 등의 기본적인 검사를 수행하여 오류가 있는지를 알려준다. 컴파일을 성공적으로 마치면 클래스 파일이 생성된다.

프로그램이 실행 중 동작을 멈춘 상태로 오랜 시간 지속되거나, 갑자기 프로그램이 실행을 멈추고 종료되는 경우 등 실행도중에 에러에 의해 런타임 에러가 발생할 수 있다. 런타임 에러를 방지하기 위해서는 프로그램의 실행 도중 발생할 수 있는 모든 경우의 수를 고려하여 이에 대한 대비를 하는 것이 필요하다. 자바에서는 실행 시 발생할 수 있는 프로그램 오류를 에러 (error)예외 (exception)으로 구분한다.

  • Error : 메모리 부족 (OutOfMemoryError)이나 스택오버플로우 (StackOverflowError)와 같이 일단 발생하면 복구할 수 없는 심각한 오류
  • Exception : 발생하더라도 수습될 수 있는 비교적 덜 심각한 오류

○ 예외 클래스

자바에서는 실행 시 발생할 수 있는 오류 (Exception과 Error)를 클래스로 정의하였다. 앞서 배운 것처럼 모든 클래스의 조상은 Object 클래스이므로 Exception과 Error 클래스 역시 Object 클래스의 자손들이다.

모든 예외의 최고 조상은 Exception 클래스이다.
예외 클래스들은 checkedunchecked로 나눠질 수 있다.

👉 checked 예외 : Exception 클래스와 그 자손들

  • 외부 영향으로 발생 할 수 있는 것으로 주로 사용자들의 동작에 의해 발생되는 경우가 많다.
  • Ex)
    • FileNotFoundException : 존재하지 않는 파일의 이름을 입력
    • ClassNotFoundException : 실수로 클래스 이름을 잘못 입력
    • DataFormatException : 입력한 데이터 형식 잘못되었음
  • 컴파일러가 예외처리 확인을 한다.
  • 예외가 발생할 가능성이 있는 문장들에 대해 예외처리를 해주지 않으면 컴파일조차 되지 않는다.

👉 unchecked 예외 : RuntimeException 클래스와 그 자손들

  • 주로 프로그래머의 실수에 의해서 발생될 수 있는 예외들로 자바의 프로그래밍 요소들과 관계가 깊다.
  • Ex)
    • ArrayIndexOutOfBoundsException : 배열의 범위를 벗어남
    • NullPointerException : 값이 null인 참조변수의 멤버를 호출
    • ClassCastException : 클래스간의 형변환 오류
    • ArithmeticException : 정수를 0으로 나누려고 함
  • 컴파일러가 예외처리 확인을 하지 않는다.
  • 프로그래머의 실수로 발생하는 것들이기 때문에 예외처리를 강제하지 않는다.

○ 예외 처리 (try - catch)

예외 처리

💡 예외처리 (exception handling)

  • 정의 : 프로그램 실행 시 발생할 수 있는 예기치 못한 예외의 발생에 대비한 코드를 작성하는 것
  • 목적 : 프로그램의 비정상 종료를 막고, 정상적인 실행상태를 유지하는 것

발생한 예외를 처리하지 못하면, 프로그램은 비정상적으로 종료되며, 처리되지 못한 예외 (uncaught exception)는 JVM의 '예외처리기 (UncaughtExceptionHandler)'가 받아서 예외의 원인을 화면에 출력한다.

try-catch문

try {
	//예외가 발생할 가능성이 있는 문장
} catch (Exception1 e1){
	//Exception1이 발생했을 경우, 이를 처리하기 위한 문장
} catch (Exception1 e2) {
	//Exception2이 발생했을 경우, 이를 처리하기 위한 문장
} finally {
	//예외의 발생여부에 관계없이 항상 수행되어야하는 문장
    //try-catch문의 맨 마지막에 위치
}
  • 하나 이상의 catch 블럭이 올 수 있으며, 해당되는 하나의 catch 블럭만 수행된다.
  • catch 블럭의 괄호 {}는 생략할 수 없다.
  • 멀티 catch 블럭 : JDK1.7 부터 여러 catch 블럭을 | 기호를 이용해서 하나의 catch 블럭으로 합칠 수 있다.
    • 예외 클래스 개수 제한은 없음
    • 연결된 예외가 상속 관계에 있다면 컴파일 에러 발생 : 부모 클래스만 쓰면된다.
    • catch 블럭 내에서는 예외 클래스들의 공통 분모인 조상 클래스 멤버만 사용 가능
try {
	...
} catch (ExceptionA | ExceptionB e){
	...
}

예외 발생 시 흐름

  1. 괄호 () 안에 처리하고자 하는 예외와 같은 타입의 참조변수를 하나 선언해야 한다.
  2. 예외가 발생하면, 발생한 예외에 해당하는 클래스의 인스턴스가 만들어 진다.
  3. 예외가 발생한 문장이 try 블럭에 포함되어 있다면, 이 예외를 처리할 수 있는 catch 블럭이 있는지 찾게 된다.
  4. catch 블럭을 차례로 내려가며 catch 블럭의 () 내에 선언된 참조변수의 종류와 생성된 예외클래스의 인스턴스에 instanceof 연산자를 이용하여 검사하고, 검사결과가 true인 catch 블럭을 만날 때까지 검사한다.
  5. true를 만나면 블럭 내 내용을 수행하고 try-catch 문을 빠져나가고, 만나지 못하면 예외는 처리되지 않는다.

예외 정보

  • printStackTrace() : 예외발생 당시의 호출스택 (Call Stack)에 있었던 메서드의 정보와 예외 메시지를 화면에 출력한다.
  • getMessage() : 발생한 예외클래스의 인스턴스에 저장된 메시지를 얻을 수 있다.

○ 예외 처리 (throws)

예외를 처리하는 방법에는 try-catch 외에 예외를 메서드에 선언하는 방법이 있다.

메서드에 예외를 선언하려면, 메서드의 선언부에 키워드 throws를 사용해서 메서드 내에서 발생할 수 있는 예외를 적어준다. 예외가 여러 개일 경우에는 쉼표로 연결해준다.

void method () throws Exception1, Exception2, .. {
}

예외를 메서드에 명시하는 것은 자신 (예외가 발생할 가능성이 있는 메서드)을 호출한 메서드에게 예외를 전달하여 예외처리를 떠맡기는 것이다.
예외를 전달받은 메서드가 또 다시 자신을 호출한 메서드에게 전달할 수 있으며, 제일 마지막에 있는 main 메서드에서도 예외가 처리되지 않으면, main 메서드마저 종료되어 프로그램이 전체가 종료된다.

결국 어느 한 곳에서는 반드시 try-catch문으로 예외처리를 해주어야 한다.

예외가 발생한 메서드 내에서 자체적으로 처리해도 되는 것은 메서드 내에서 try-catch 문을 사용해서 처리하고, 메서드에 호출 시 넘겨받아야 할 값을 다시 받아야 하는 경우 (메서드 내에서 자체적으로 해결이 안 되는 경우)에는 예외를 메서드에 선언해서, 호출한 메서드에서 처리해야 한다.

Java API의 Throws:

Java API 문서를 통해 사용하고자 하는 메서드의 선언부와 "Throws:"를 보고, 이 메서드에서는어떤 예외가 발생할 수 있으며 반드시 처리해주어야 하는 예외는 어떤 것들이 있는지 확인하는 것이 좋다.

profile
훈이야 화이팅
post-custom-banner

0개의 댓글