-
[live-study] 9주차 :: 예외 처리JAVA/라이브 스터디 | whiteship 2021. 2. 6. 22:16
참고도서 : Java의 정석(3rd Edition), Java in a Nutshell
0. 예외처리란
프로그램 에러 (오류)
- 프로그램이 실행 중 어떤 원인에 의해서 오작동을 하거나 비정상적으로 종료되는 경우가 있는데, 이러한 결과를 초래하는 원인을 프로그램 에러(오류)라고 말한다.
- 컴파일 에러(compile-time error) : 컴파일 시점에 발생하는 에러
- 런타임 에러(runtime error) : 프로그램 실행 도중에 발생하는 에러
- 논리적 에러(logical error) : 실행과 컴파일은 문제가 없지만, 논리적인 오류가 있어서 발생하는 에러
예외처리 (Exception Handling)
- 예외처리란 프로그램 실행 시 발생할 수 있는 예기치 못한 예외의 발생에 대비해 미리 코드를 작성하는 것이다.
- 그래서 예외의 발생으로 인해 실행 중인 프로그램이 갑작스럽게 비정상적으로 종료되는 것을 막을 수 있다.
- 만약, 발생한 예외를 처리하지 못한다면, 프로그램은 비정상적으로 종료되게 된다.
- 또한, 처리되지 못한 예외(uncaught exception)은 JVM의 예외처리기(UncaughtExceptionHandler)가 원인을 화면에 출력한다.
1. 자바에서 예외 처리 방법 (try, catch, throw, throws, finally)
try - catch
- 이러한 예외를 처리하기 위해서 try-catch문을 사용한다.
- try-catch문에서 try 블럭내에서 예외가 발생하는경우, 발생한 예외와 일치하는 catch 블럭을 찾는다. 만약 찾는다면 catch 블럭내의 코드를 수행하고, 다음 코드를 수행하지만 만약 찾지 못한다면 예외처리가 불가능하다.
- try블럭내에서 예외가 발생하지 않다면, 일반적인 코드 수행 처럼 try블럭내 코드만 수행 한 후 catch 블럭을 거치지 않고 try-catch문을 빠져나가 다음 코드를 수행한다.
- 아래와 같이 0으로 나누려했을때 예외처리를 하지 않으면 ArithmeticException이 발생하고 프로그램이 비정상적으로 종료된다.
- 하지만 try-catch문을 이용하여 예외처리를 해주면 예외가 발생하여 "예외발생"이라는 문구가 출력되긴 하지만, 프로그램이 비정상적으로 종료되지는 않는다.
- 예외가 발생하면 발생한 예외에 해당하는 클래스의 인스턴스가 만들어진다. 그리고 예외가 발생한 문장이 try 블럭내에 포함되어 있다면, 이 예외를 처리할 수 있는 catch 블럭을 찾는다.
- catch블럭에서는 블럭의 괄호( ) 내에서 선언된 참조변수의 종류와 생성된 예외클래스의 인스턴스의 instanceof 연산자를 이용하여 검사하게 되는데, 검사결과가 true인 catch 블럭을 만날 때 까지 검사를 계속한다. true를 찾게 된다면 블럭 내 문장을 모두 수행한 후 try-catch문을 빠져나가게 되지만, 찾지 못할 경우 예외처리는 수행되지 않는다.
printStackTrace(), getMessage()
- 예외가 발생했을 때 생성되는 예외 클래스의 인스턴스에는 발생한 예외에 대한 정보가 담겨져 있으며, 이는 printStackTrace()와 getMessage()를 통해 얻을 수 있다.
- printStackTrace()는 예외발생 당시의 호출스택(Call Stack)에 있었던 메소드의 정보와 예외 메시지를 출력한다.
- getMessage()는 발생한 예외클래스의 인스턴스에 저장된 메시지를 출력한다.
throw
- 키워드 thorw를 사용하여 프로그래머가 고의로 예외를 발생시킬 수 있다.
throws
- 예외를 처리하는 방법에는 try-catch문 외에 예외를 메소드에 선언하는 throws라는 키워드가 있다.
- 메소드의 선언부에 키워드 throws를 사용해서, 메소드내에서 발생할 수 있는 예외를 적어주면 된다. 여러개를 선언할 수 있으며 콤마(,)로 구분한다.
- 만약, 예외의 최고조상인 Exception 클래스를 메소드에 선언하면, 모든 종류에 대해 예외가 발생할 가능성이 있다는 뜻이다.
finally
- finally 블럭은 예외의 발생여부에 상관없이 실행되어야할 코드를 포함시킬 목적으로 사용된다. try-catch문의 끝에 '선택적'으로 덧붙여 사용할 수 있으며, try-catch-finally 순서이다.
- 즉, 예외가 발생하는 경우 try -> catch -> finally 순으로 실행되고, 예외가 발생하지 않는다면 try - > finally 순으로 실행된다.
- 아래 예시처럼 try에 retrun문이 있다하더라도 무조건 finally까지 수행이 된다.
try - with - resource
- Java 8부터 try-with-resource문이라는 try-catch문의 변형문이 새로 추가되었다.
- 주로 I/O(입출력)와 관련된 클래스들을 사용할 때 유용한데, 입출력에 사용되는 클래스 중에는 사용한 후에 꼭 닫아 줘야 하는 것들이 있다. 그래야 사용했던 자원(resources)이 반환되기 때문이다.
2. 자바가 제공하는 예외 계층 구조
예외클래스 계층도
- 자바에서는 실행시 발생할 수 있는 오류(Exception과 Error)를 클래스로 정의하였다.
- 모든 클래스의 조상은 Object 클래스 이므로, Excpetion과 Error 클래스 역시 Object클래스의 자식 클래스이다.
Exception클래스와 RuntimeExcetpion클래스 중심의 상속계층도
- 모든 예외의 최고 조상은 Exception 클래스이다.
- 그리고 아래와 같이 Exception클래스와 그 자식들(RuntimeException 제외), 그리고 RuntimeException클래스와 그 자식들로 나눌 수 있다.
- RuntimeException은 주로 프로그래머의 실수에 의해서 발생될 수 잇는 예외들로 자바의 프로그래밍 요소들과 관계가 깊다. 아래 예시 처럼 정수를 0으로 나누려고 할 때 발생하는 ArithmeticException이나, 값이 null인 참조변수를 호출할 때 발생하는 NullPointerException 같은 경우가 있다.
- 즉, Excption클래스들은 사용자의 실수와 같은 외적인 요인에 의해 발생하고, RuntimeException클래스들은 프로그래머의 실수로 발생하는 예외이다.
3. Exception과 Error의 차이는?
예외(Exception)과 오류(Error)
- 소스코드(.java)를 컴파일 했을 때 오류가 없으면 클래스 파일(.class)이 생성되고 클래스 파일을 실행할 수 있게 만들어진다. 하지만 컴파일이 성공적으로 수행되었다고 하더라도, 실행 중에 에러가 발생하여 동작이 멈춘 상태로 지속되거나, 프로그램이 실행을 멈출 수도 있다.
- 이러한 런타임 에러를 방지하기 위해 프로그램의 실행도중 발생할 수 있는 경우의 수를 고려하여 대비하는 것이 필요한데, 자바에서는 이를 에러(error)와 예외(exception)으로 나눈다.
- 에러(error)는 메모리 부족(OutOfMemoryError)이나 스택오버플로우(StackOverFlowError)와 같이 일단 발생하면 복구할 수 없는 심각한 오류이다.
- 예외(Exception)은 발생하더라도 이에 대한 적절한 코드를 미리 작성해 놓으면 프로그램의 비정상적인 종료를 막을 수 있다.
4. RuntimeException과 RE가 아닌 것의 차이는?
Exception (RE 제외)
- 아래와 같이 코드를 작성한 후 컴파일 하려고 하면, 아래와 같은 에러가 발생하여 컴파일이 완료되지 않을 것이다. 예외처리를 해야할 부분에 예외처리가 되어 있지 않다라는 뜻이다.
- 즉, Exception클래스들(Exception클래스와 그 자식들)은 예외가 발생할 가능성이 있는 부분에 예외처리를 해주지 않으면 컴파일이 되지 않는다.
- 이렇게 컴파일러가 예외처리를 확인하는 Exception클래스들은 'Checked Exception' 이라고 부른다.
RuntimeException
- 하지만, RuntimeException을 똑같은 방법으로 작성하면 컴파일이 될 것이다. 하지만, 아래 실행결과처럼 RuntimeException이 발생하고 비정상적으로 종료될 것이다.
- 앞서 설명한 것처럼 Exception클래스들과 달리 RuntimeException클래스들은 프로그래머의 실수로 인해 발생하기 때문에 강제로 예외처리를 당하지 않는다.
- 이처럼, 컴파일러가 예외처리를 하지 않는 RuntimeException 클래스들은 'Unchecked Exception'라고 부른다.
- 만약 RuntimeException클래스들에 속하는 예외가 발생할 것 같으면 아래와 같은 예시처럼 예외처리를 해주어야한다.
5. 커스텀한 예외 만드는 방법
커스텀한 예외
- 기존의 정의된 예외 클래스 외에 필요에 따라 프로그래머가 새로운 예외 클래스를 커스텀하게 정의하여 사용할 수 있다.
- 보통 Exception클래스 또는 RuntimeException클래스로부터 상속받아 클래스를 만들지만, 필요에 따라 알맞은 예외 클래스를 선택할 수 있다.
'JAVA > 라이브 스터디 | whiteship' 카테고리의 다른 글
[live-study] 11주차 :: Enum (0) 2021.02.15 [live-study] 10주차 :: 멀티쓰레드 프로그래밍 (0) 2021.02.15 [live-study] 8주차 :: 인터페이스 (0) 2021.01.30 [live-study] 7주차 :: 패키지 (0) 2021.01.24 [live-study] 6주차 :: 상속 (0) 2021.01.09