java

java_Chapter08_예외처리

강용민 2023. 3. 10. 23:15

1. 예외처리

1.1 프로그램 오류

오류는 발생시점에 따라  컴파일 에러(compile time error)와 런타임 에러(runtime error)로 나눈 수 있는데, 컴파일 에러는 컴파일 할 때 발생하는 에러이고 프로그램의 실행도중에 발생하는 에러를 런타임 에러라 한다. 이 외에도 논리적 에러(logical error)가 있는데 이는 의도와 다르게 동작하는 것을 말한다.

자바에서는 실행 시(runtime) 발생할 수 있는 프로그램 오류를 에러(error)와 예외(exception) 두 가지로 구분했다.

에러는 프로그램 코드에 의해서 수습될 수 없는 심각한 오류고, 예외는 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류이다. 예외는 발생하더라도 프로그래머가 이에 대한 적절한 코드를 미리 작성해 놓음으로써 프로그램의 비정상적인 종료를 막을 수 있다.

 

1.2 예외 클래스의 계층구조

위 그림은 예외 클래스 계층도이다. 모든 예외의 최고 조상은 Exception클래스이며, 상속 계층도를 Exception클래스부터 도식화하면 다음과 같다.

Exception을 크게 둘로 나눈다면 RuntimeException 클래스(및 자손 클래스)와 RuntimeException 클래스를 제외한 클래스(및 자손 클래스)로 나눌 수 있는데 RuntimeException클래스는 프로그래머의 실수로 발생하는 예외이고, 그 외 Exception클래스는 사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외를 뜻한다.

 

1.3 예외처리하기(try-catch문)

try-catch문에서 예외가 발생한 경우와 발생하지 않았을 때의 흐름이 달라지는데, 아래에 이 두 가지 경우에 따른 문장 실행순서를 정리하였다.

  • try블럭 내에서 예외가 발생한 경우
    • 발생한 예외와 일치하는 catch블럭이 있는지 확인한다.
    • 일치하는 catch블럭을 찾게 되면, 그 catch 블럭 내의 문장들을 수행하고 전체 try catch문을 빠져나가서 그 다음 문장을 계속해서 수행한다. 만약 일치하는 catch블럭을 찾지 못하면, 예외는 처리되지 못한다.
  • try블럭 내에서 예외가 발생하지 않는 경우
    • catch블럭을 거치지 않고 전체 try-catch문을 빠져나가서 수행을 계속한다.

 

1.7 메서드에 예외 선언하기

메서드에 예외를 선언하려면, 메서드의 선언부에 키워드 throws를 사용해서 메서드 내에서 발생할 수 있는 예외를 적어주기만 하면된다. 그리고 예외가 여러 개일 경우에는 쉼표로 구분한다.

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

사실 예외를 메서드의 throws에 명시하는 것은 예외를 처리하는 것이 아니라, 자신(예외가 발생할 가능성이 있는 메서드)ㄹ을 호출한 메서드에게 예외를 전달하여 예외처리를 떠맡기는 것이다. 예외를 전달받은 메서드가 또다시 자신을 호출한 메서드에게 전달할 수 있으며, 이런 식으로 계속 호출스택에 있는 메서드들을 따라 전달되다가 제일 마지막에 있는 main 메서드에서도 예외가 처리되지 않으면, main메서드마저 종료되어 프로그램이 전체가 종료된다. 결국 어느 한 곳에서는 반드시 try-catch문으로 예외처리를 해주어야 한다.

 

1.8 finally블럭

finally블럭은 예외의 발생여부에 상관없이 실행되어야할 코드를 포함시킬 목적으로 사용된다. try블럭에서 return문이 실행되는 경우에도 fianlly블럭의 문장들이 먼저 실행된 후에, 현재 실행 중인 메서드를 종료한다. 이와 마찬가지로 catch블럭의 문장 수행 중에 return문을 만나도 finally블럭의 문장들은 수행된다.

 

1.10 사용자정의 예외 만들기

기존의 정의된 예외 클래스 외에 필요에 따라 프로그래머가 새로운 예외 클래스를 정의하여 사용할 수 있다. 보통 Exception클래스 또는 RuntimeException클래스로부터 상속받아 클래스를 만들지만, 필요에 따라서 알맞은 예외 클래스를 선택할 수 있다.

기존의 예외 클래스는 주로 Exxception을 상속받아서 'cheked예외'로 작성하는 경우가 많았지만 요즘은 예외처리를 선택적으로 할 수 있도록 RuntimeException을 상속받아서 작성하는 쪽으로 바뀌어가고 있다. 'checked 예외'는 반드시 예외처리르 해주어야 하기 때문에 예외처리가 불필요한 경우에도 try-catch문을 넣어서 코드가 복잡해지기 때문이다.

 

1.11 예외 되던지기(excpetion re-throwing)

한 메서드에서 발생할 수 있는 예외가 여럿인 경우, 몇 개는 try-catch문을 통해서 메서드 내에서 자체적으로 처리하고, 그 나머지는 선언부에 지정하여 호출한 메서드에서 처리하도록 함으로써 양쪽에서 나눠서 처리되도록 할 수 있다. 그리고 심지어는 단 하나의 예외에 대해서도 예외가 발생한 메서드와 호출한 메서드, 양쪽에서 처리하도록 할 수 있다.

이것은 예외를 처리한 후에 인위적으로 다시 발생시키는 방법을 통해서 가능한데, 이것을 '예외 되던지기(expception re-throwing)'라고 한다. 

이 방법은 하나의 예외에 대해서 예외가 발생한 메서드오 이를 호출한 메서드 양쪽 모두에서 처리해줘야 할 작업이 있을 때 사용된다. 이 때 주의할 점은 예외가 발생할 메서드에서는 try-catch문을 사용해서 예외처리를 해줌과 동시에 ㅁ네서드의 선언부에 발생할 예외를 throws에 지정해줘야 한다는 것이다.

 

1.12 연결된 예외(chained exception)

한 예외가 다른 예외를 발생시킬 수도 있다. 발생한 예외를 원인 예외로 등록해서 다시 예외를 발생시키는 이유는 여러가지 예외를 하나의 큰 분류의 예외로 묶어서 다루기 위해서이다. 또 다른 이유는 checked예외를 unchecked예외로 바꿀 수 있도록 하기 위해서이다.checked예외는 예외처리를 강제하는데 checked예외가 발생해도 예외를 처리할 수 없는 상황이 생기며, 이때 할 수 있는 일이라고는 의미없는 try-catch문을 추가하는 것뿐이다. 이를 unchecked예외로 바구면 예외처리가 선택적이 되므로 억지로 예외처리를 하지 않아도 된다.

 

문제

1. 에러는 두 가지 종류로 나눌 수 있다. 어떻게 나눌 수 있는가??

- 에러는 Error와 Exception으로 나눌 수 있다. Error는 코드적으로 수습될 수 없는 에러를 말하며, Exception는 코드적으로 수습할 수 있는 미약한 에러를 뜻한다.

 

2. Exception도 두 가지 종류로 나눌 수 있다. 어떻게 나눌 수 있는가??

- Exception는 RuntimeException과 RuntimeException이 아닌 Exception으로 나눌 수 있다. RuntimeException의 경우 프로그래머의 실수로 나올 수 있는 Exception을 뜻하며, 그외 Exception은 사용자의 잘못된 입력등의 외부적인 요인으로 발생하는 Exception을 뜻한다.

- RuntimeException의 경우 unchecked Exception으로 필수적으로 예외처리 할 필요는 없지만 그 외의 Exception의 경우 checked Exception으로 필수적으로 예외처리해야 한다. 하지만 Exception 중 예외 처리할 수 없는 예외가 생기며 이는 RuntimeException으로 변경하면 불필요한 처리를 하지 않을 수 있다.

 

3. 예외처리는 try-catch와 throws를 통해 처리할 수 있다. 이 두 가지의 차이는 무엇이 있는가??

- try-catch문은 Exception이 일어난 메서드를 호출한 쪽, 즉 책임을 자기 자신이 지고있다. 하지만 throws는 본인이 처리할 수 없는 예외를 자신을 호출한 쪽, client에게 예외처리를 전가한다.

 

4. exception re-throwing은 보통 언제 사용하는가??

exception re-throwing은 몇 개의 예외는 본인이 처리하고 나머지는 호출한 쪽에 책임을 전가하는 것인데, 모든 예외를 본인이 처리하기 어렵다는 판단이 들때 호출한 쪽(client)에 예외를 던짐으로써 client가 예외를 처리해야 할 때 사용한다.

'java' 카테고리의 다른 글

java_chapter13_쓰레드  (0) 2023.03.11
java_chapter12_generics, enumeration, annotation  (0) 2023.03.11
Java_Chapter08_객체 지향 4대 요소  (0) 2022.10.09
Java_Chapter?_builder pattern  (0) 2022.10.06
Java_Chapter07_클래스의 관계  (0) 2022.09.15