예외 처리가 필요한 이유
외부 서버와 통신할 때 다음과 같은 다양한 문제들이 발생할 수 있다.
- 네트워크 오류 등으로 인해 외부 서버와 연결에 실패
- 데이터 전송에 문제가 발생
자바의 예외 처리 메커니즘 제공
자바는 프로그램 실행 중에 발생할 수 있는 예상치 못한 상황, 즉 예외(Exception)를 처리하기 위한 메커니즘을 제공한다. 이는 프로그램의 안정성과 신뢰성을 높이는 데 중요한 역할을 한다.
자바의 예외 처리는 다음 키워드를 사용한다. 그리고 예외를 다루기 위한 예외 처리용 객체들을 제공한다.
- try
- catch
- finally
- throw
- throws
예외 계층 구조
- Exception : 체크 예외
- 애플리케이션 로직에서 사용할 수 있는 실질적인 최상위 예외이다.
- Exception과 그 하위 예외는 모두 컴파일러가 체크하는 체크 예외이다. 단 RuntimeException은 예외로 한다.
- RuntimeException : 언체크 예외, 런타임 예외
- 컴파일러가 체크 하지 않는 언체크 예외이다.
- RuntimeException 과 그 자식 예외는 모두 언체크 예외이다.
- RuntimeException 의 이름을 따라서 RuntimeException 과 그 하위 언체크 예외를 런타임 예외라고 많이 부른다.
📌 주의
상속 관계에서 부모 타입은 자식을 담을 수 있다. 예외 처리에서도 상속 예외를 catch로 잡으면 그 하위 예외까지 함께 잡을 수 있다는 특징이 있다. 따라서 애플리케이션 로직에서는 Throwable 예외를 잡으면, 잡으면 안 되는 Error 예외도 함께 잡을 수 있기 때문에 Throwable 예외는 잡으면 안 된다. 애플리케이션 로직은 이런 이유로 Exception 부터 필요한 예외로 생각하고 잡으면 된다.
📌 예외 2가지 기본 규칙
- 예외는 잡아서 처리하거나 밖으로 던져야 한다.
- 예외를 잡거나 던질 때 지정한 예외뿐만 아니라 그 예외의 자식들도 함께 처리될 수 있다.
체크 예외
1. Exception 상속
public class MyCheckedException extends Exception {
public MyCheckedException(String message) {
super(message);
}
}
- 예외 클래스를 만들려면 예외를 상속 받으면 된다.
- Exception을 상속받은 예외는 체크 예외가 된다.
2. throws, throw 키워드
public class Client {
public void call() throws MyCheckedException {
throw new MyCheckedException("ex");
}
}
- throw 예외라고 하면 새로운 예외를 발생시킬 수 있다. 예외도 객체이기 때문에 객체를 먼저 new로 생성하고 예외를 발생시켜야 한다.
- throws 예외는 발생시킨 예외를 메서드 밖으로 던질 때 사용하는 키워드이다.
3. try, catch 키워드
public class Service {
Client client = new Client();
public void callCatch() {
try {
client.call();
} catch (MyCheckedException e) {
//예외 처리 로직
System.out.println("예외 처리, message = " + e.getMessage());
}
System.out.println("정상 흐름");
}
public void callThrow() throws MyCheckedException {
client.call();
}
}
- callCatch() 는 예외를 잡아서 처리하는 코드이다.
- client.call() 을 호출하면 Client 클래스에서 예외가 발생한다.
- Client 클래스에서 예외가 발생하면 throws 로 인해 메서드 밖으로 던져진다.
- 던져진 걸 catch 문에서 잡을 수 있다.
- callThrow() 는 체크 예외를 밖으로 던지는 코드이다.
- 체크 예외는 예외를 잡지 않고 밖으로 던지려면 throws 예외를 메서드에 필수로 선언해야 한다.
💡정리
체크 예외는 예외를 잡아서 처리할 수 없을 때, 예외를 밖으로 던지는 throws 예외 를 필수로 선언해야 한다. 그렇지 않으면 컴파일 오류가 발생한다. 개발자가 예외를 직접 명시하여 컴파일러를 통해 어떤 체크 예외가 발생하는지 쉽게 파악할 수 있다는 장점이 있지만, 실제로 개발자가 모든 체크 예외를 반드시 잡거나 던지도록 처리해야 하기 때문에 번거롭다는 단점이 있다.
언체크 예외
1. RuntimeException 상속
public class MyUncheckedException extends RuntimeException {
public MyUncheckedException(String message) {
super(message);
}
}
- RuntimeException을 상속받은 예외는 언체크 예외가 된다.
2. throw 키워드
public class Client {
public void call() {
throw new MyUncheckedException("ex");
}
}
- 체크 예외에서는 throws 예외를 명시해주었는데, 언체크 예외에서는 생략해도 된다.
3. try, catch 키워드
public class Service {
Client client = new Client();
/**
* 필요한 경우 예외를 잡아서 처리하면 된다.
*/
public void callCatch(){
try {
client.call();
} catch (MyUncheckedException e) {
//예외 처리 로직
System.out.println("예외 처리, message = " + e.getMessage());
}
System.out.println("정상 로직");
}
public void callThrow() {
client.call();
}
}
- callCatch() 는 예외를 잡아서 처리하는 코드이다.
- 필요한 경우에 예외를 잡아서 처리할 수 있다.
- callThrow() 는 예외를 밖으로 던지는 코드이다.
- 언체크 예외는 체크 예외와 다르게 throws 예외 를 선언하지 않아도 된다.
- 말 그대로 컴파일러가 이런 부분을 체크하지 않기 때문에 언체크 예외이다.
💡정리
언체크 예외는 예외를 잡아서 처리할 수 없을 때, 예외를 밖으로 던지는 throws 예외 를 생략할 수 있다. 신경쓰고 싶지 않은 언체크 예외를 무시할 수 있다는 장점이 있지만, 개발자가 실수로 예외를 누락할 수 있다는 단점이 있다.
체크 예외와 언체크 예외의 차이
- 체크 예외 : 예외를 잡아서 처리하지 않으면 항상 throws 키워드를 사용해서 던지는 예외를 선언해야 한다.
- 언체크 예외 : 예외를 잡아서 처리하지 않아도 throws 키워드를 생략할 수 있다.
'자바 > 자바 중급' 카테고리의 다른 글
[자바 중급] 11. Generic 1 (2) | 2024.11.06 |
---|---|
[자바 중급] 10. 예외 처리 2 (1) | 2024.10.22 |
[자바 중급] 08. 중첩 클래스, 내부 클래스 2 (3) | 2024.10.11 |
[자바 중급] 07. 중첩 클래스, 내부 클래스 1 (1) | 2024.10.09 |
[자바 중급] 06. 날짜와 시간 (1) | 2024.10.09 |