일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- Blue-Green
- ci/cd
- BalancedTree
- 카카오 2차 코딩테스트
- 월간회고
- 기능별 구조
- 주간회고
- DeleteAll
- N+1
- 회고
- jacoco
- 블로그 병행
- mysql
- Jenkins
- java
- db
- 도커
- 멀티쓰레드 프로그래밍
- 프리코스
- SQL 실행순서
- 우테코
- 메서드명
- useQuery
- useMutation
- 어댑티브 해시 인덱스
- 클래스
- InnoDB 버퍼 풀
- 계층별 구조
- B+TREE
- 백기선 스터디
- Today
- Total
Haneul's Blog
[Java] 예외 처리 본문
목표 [백기선 자바 스터디 9주차]
자바의 예외 처리에 대해 학습하세요.
학습할 것
- 자바에서 예외 처리 방법 (try, catch, throw, throws, finally)
- 자바가 제공하는 예외 계층 구조
- Exception과 Error의 차이는?
- RuntimeException과 RE가 아닌 것의 차이는?
- 커스텀한 예외 만드는 방법
자바에서 예외 처리를 하는 방법을 알아보기 전에 먼저 예외(Exception)란 무엇이고 에러(Error)란 무엇인지 그리고 이 둘의 차이를 잠깐 정리하겠습니다.
예외(Exception)와 에러(Error)
에러는 시스템의 비정상적인 상황이 생겨 프로그램이 비정상적으로 종료되는 것입니다.
이러한 에러는 컴파일 에러와 런타임 에러로 구분할 수 있는데, 컴파일 에러는 말 그대로 컴파일 과정에서 일어나는 에러이고, 런타임 에러는 실행 과정에서 일어나는 에러입니다. 즉, 에러가 발생하는 시점에 따라서 에러를 구분할 수 있습니다.
컴파일 에러는 기본적으로 자바 컴파일러가 문법을 검사하면서 오류를 잡아내주고 이를 통해서 오류를 수정하면 성공적으로 컴파일을 하여 프로그램을 실행 할 수 있게 됩니다.
하지만 컴파일이 문제 없이 되더라도 실행 과정(Runtime)에서 오류가 발생할 수 있는데, 이를 런타임 에러라고 합니다. 이를 방지하기 위해서는 프로그램 실행 중에 일어날 수 있는 경우의 수를 모두 대비할 필요성이 있습니다.
자바에서는 이러한 런타임 에러를 예외(Exception)와 에러(Error) 두 가지로 구분하여 대응하고 있습니다.
에러(Error)는 메모리 부족(OutOfMemoryError), 스택오버플로우(StackOverFlowError)와 같이 JVM이나 하드웨어 등의 기반 시스템 문제로 발생하는 것이기 때문에, 개발자가 따로 할 수 있는게 없습니다.
그러나 예외(Exception)는 발생하더라도 개발자가 프록그램이 비정상적으로 종료되지 않도록 코드를 작성하여 핸들링 해줄 수 있다는 점이 에러와 다릅니다.
이러한 Exception과 Error는 자바에서는 클래스로 지정되어 있습니다. 아래의 그림을 보면 그 구조를 알 수 있습니다.
이 계층 구조를 보면 Error나 Exception 모두 Throwable을 상속받고 있고 Throwable은 모든 클래스의 최상위 클래스인 Object 클래스를 직접 상속 받고 있다는 것을 알 수 있습니다. 또한 Unchecked Exception과 Checked Exception이라는 개념이 나오는데 이는 아래에서 설명하겠습니다.
Check Exception과 Unchecked Exception
위 그림을 보면 Exception을 상속받는 클래스 중 RuntimExcepion과 그 하위 클래스들을 제외하고는 모두 CheckedExcepion이라고 표시되어 있는 것을 확인할 수 있습니다.
여기서 CheckedException은 컴파일 시점에서 확인될 수 있는 예외로 만약 코드 내에서 Checked Excepion을 발생시킨다면 해당 예외는 반드시 처리되거나 해당 코드가 속한 메서드의 선언부에 예외를 선언해주어야 합니다. 이러한 예외 처리를 해주지 않으면 아예 컴파일 자체가 되지 않기 때문에 필수로 위와 같은 처리를 해주어야 합니다.
그렇다면 UnCheckedException은 CheckedException과 반대되는 개념이라는 것을 예측할 수 있을 것입니다.
즉 UnCheckedException은 컴파일 단계에서 확인되지 않으며 이 예외들은 컴파일러가 예외를 처리하거나 선언하도록 강제하지 않습니다. 따라서 개발자가 이를 처리해야 합니다.
위 그림을 보면 알 수 있다시피 Error와 Exception 클래스의 RuntimeException과 그 하위 클래스들이 UncheckedException에 해당한다고 할 수 있습니다.
그렇다면 왜 이와 같이 CheckedException과 UnCheckedException으로 구분되었을까요?
메서드를 호출하는 쪽은 그 메서드가 어떤 예외를 발생시킬 수 있는지를 반드시 알아야 합니다. 따라서 Java는 CheckedException을 통해 해당 메서드가 발생시킬 수 있는 예외를 명세하도록 강제하고 있습니다.
하지만 이상한 점이 있습니다. RuntimException도 예외가 발생되는 것인데 왜 예외를 명세하지 않는 것일까요?
RuntimeException은 개발자가 코드를 잘못 짠 탓에 프로그램 코드 문제로 발생하는 예외입니다. 따라서 메서드를 호출하는 쪽에서 이를 복구하거나 대처할 수 있을 거라고 예상하기 힘들고, 또한 프로그램 어디서나 많이 발생할 수 있기 때문에 모든 RuntimeException을 메서드에 명시하도록 하는 것은 프로그램의 명확성을 떨어뜨릴 수 있기 때문에 UnCheckedException으로 분류하였습니다.
정리하자면 메서드를 호출한 쪽에서 Exception을 회복시킬 수 있겠다고 예상된다면 CheckedException 아니라면 UnCheckedException으로 구분하면 좋을 것 같습니다.
그렇다면 이러한 예외는 어떻게 핸들링 해줄 수 있는지 아래에서 알아보겠습니다.
자바의 예외 처리 방법 (try, catch, throw, throws, finally)
먼저 try-catch-finally에 대해서 알아보겠습니다.
try-catch-finally는 예외가 발생한 메서드 내에서 직접 처리하고자 할 때 작성되는 코드입니다. (메서드 측에서 예외를 던지고 메서드를 호출한 쪽에서도 처리가 가능합니다.)
try
try 블록은 예외가 발생할 가능성이 있는 범위를 지정하는 블록으로 최소한 하나의 catch 블록도 가져야 하며 catch 블록은 try블록 다음에 위치합니다.
catch
블록은 매개변수의 예외 객체가 발생했을 때 참조하는 변수명으로 반드시 java.lang.Throwable 클래스의 하위 클래스 타입으로 선언되어야 합니다.
try 블록에서 예외가 발생한다면 try 블록의 나머지 문장들은 수행되지 않고, JVM은 발생한 예외 객체를 발생시키며 발생한 예외 객체 타입이 동일한 catch 블록을 수행합니다.
catch문은 여러 개의 블록으로 구성할 수 있으며 주의할 점은, catch블럭 작성 시에 부모 클래스가 먼저 catch에서 쓰이게 된다면 컴파일 에러가 발생하게 됩니다.
finally
finally는 try와 catch처럼 필수 블록은 아닙니다.
간단하게만 설명하자면 finally이 블록이 사용된다면 작성된 내용은 예외가 발생하건 안하건 무조건 수행됩니다. 따라서, 데이터베이스나 파일을 사용 후에 닫는 기능과 같이 항상 수행해야 할 필요가 있는 경우에 사용됩니다.
아래는 try-catch-finally를 사용한 예시입니다.
throws
예외가 발생한 메서드를 호출한 곳으로 예외를 넘기는 방법입니다.
throw
throw는 예외를 인위적으로 발생시키는 것으로 개발자가 의도하지 않은 케이스에 대해서 임의로 예외를 발생시키려고 할 떄 사용되며, 특정 예외를 만났을 때 더욱 구체적인 예외로 처리하고자 할 때도 사용됩니다.
커스텀한 예외 만드는 방법
자바가 가지고 있는 많은 예외 클래스가 있지만 실제 애플리케이션을 모두 커버하기에는 케이스가 적습니다. 따라서 사용자가 커스텀한 예외를 만들어서 사용합니다.
아래는 Custom Exception을 만드는 예시입니다.
public class CustomException extends Exception{
public CustomException(){} // 기본 생성자
public CustomException(String message){
super(message); // 에러메세지 생성자
}
}
public void runCustomException() {
throw new CustomExcetpion("사용자 에러 임의로 발생 시키기");
}
'Java' 카테고리의 다른 글
[Java] Enum (0) | 2022.10.23 |
---|---|
[Java] 멀티쓰레드 프로그래밍 (0) | 2022.10.22 |
[Java] 인터페이스 (0) | 2022.10.19 |
[Java] 패키지 (0) | 2022.10.18 |
[Java] 상속 (0) | 2022.10.17 |