📔 학습한 내용을 정리하기 위해 작성하는 게시글입니다.
오류(error
) : 자바 가상 머신 자체에서 발생하는 오류로, 개발자가 해결할 수 없는 오류
ex) 메모리가 꽉 찬 경우, 스레드가 죽은 경우, 블루스크린
예외(exception
) : 연산 오류, 숫자 포맷 오류 등과 같이 상황에 따라 개발자가 해결할 수 있는(오류 자체를 수정할 수 있다는 뜻이 아님, 오류가 발생했을 때 차선책을 선택하는 것) 오류
예외 처리(Exception Handling) : 오류가 발생했을 때 차선책을 제시함으로써 오류를 피하는 과정
→ 개발자가 예외 처리하면 프로그램은 종료되지 않고 계속 실행된다.
java.lang.Exception
을 상속 받는다.Exception
모두 Throwable
클래스를 상속하고 있다.일반 예외(=검사형 예외, Checked Exception)
- 예외 처리를 하지 않으면 컴파일 오류가 발생하므로 꼭 처리해야 하는 검사형 예외
- 컴파일 단계에서 체크
- 예외 처리 필수
roll-back
안함
실행 예외(Unchecked Exception=Runtime Exception)
- 예외 처리를 하지 않아도 컴파일할 수 있는 비검사형 예외
RuntimeException
클래스를 상속받은 클래스- 실행 단계에서 체크
- 예외 처리 생략 가능(필요에 따라 처리)
roll-back
함
일반 예외 종류 | 발생 이유 |
---|---|
ClassNotFoundException | 존재하지 않는 클래스를 사용하려고 할 때 발생 |
NoSuchFieldException | 클래스가 명시한 필드를 포함하지 않을 때 발생 |
IOException | 데이터 읽기 쓰기 같은 입출력 문제가 있을 때 발생 |
실행 예외 종류 | 발생 이유 |
---|---|
ArtithmeticException | 0으로 나누기와 같은 부적절한 산술 연산을 수행할 때 발생 |
IllegalArgumentException | 메서드에 부적절한 매개변수를 전달할 때 발생 |
IndexOutOfBoundException | 배열, 벡터 등에서 범위를 벗어난 인덱스를 사용할 때 발생 |
NoSuchElementException | 요구한 원소가 없을 때 발생 |
NullPointerException | null값을 가진 참조 변수에 접근할 때 발생 |
NumberFormatException | 숫자로 바꿀 수 없는 문자열을 숫자로 변환하려 할 때 발생 |
예외 처리 방법에는
1) 예외 복구 2) 예외 회피 3) 예외 전환 4) 사용자 정의 예외가 있다.
예외 상황을 파악하고 문제를 해결해서 정상 상태로 돌려놓는 방법
(기본 작업 흐름이 불가능하면 다른 작업 흐름으로 자연스럽게 유도)
예외 처리 문법은 크게 3가지 요소(try
, catch
, finally
)로 구성되어 있다.
try {
//일반 예외, 실행 예외 발생 가능성이 있는 코드
} catch (예외 클래스명 참조 변수명) {
//try 블록에서 예외가 발생했을 때 처리
} finally { //생략 가능
//예외 발생 여부에 상관없이 무조건 실행
}
try {
//...
} catch (예외 타입 e1) {
//...
} catch (예외 타입 e2) {
//...
}
...
finally {
//...
}
try {
//...
} catch (예외 타입 e1 | 예외 타입 e2) {
//...
}
...
finally {
//...
}
try{}
블록에서 예외가 발생하고, 여러 개의 catch(){}
블록이 있을 때 실행할 catch(){}
블록의 선택 과정은 항상 위에서부터 확인한다.try (리소스 자동 해제가 필요한 객체 생성) {
//예외 발생 가능 코드
}
catch (예외 클래스명 참조 변수명) {
//해당 예외가 발생했을 때 처리하는 블록
}
finally {
//예외 발생 여부에 상관없이 무조건 실행하는 블록
}
리소스 해제는 더이상 사용하지 않는 자원을 반납하는 것
예외의 발생 여부와 관계 없이 예외 처리 구문이 완료된 후 리소스 객체의 close()
메서드를 자동으로 호출해 줌
→ 리소스 객체 내부에 close()
메서드가 있어야 자동 해제를 할 수 있는 객체가 됨
리소스 자동 해제 객체는 반드시 close()
메서드를 포함해야 함 = 리소스 자동 해제 객체는 AutoCloseable
인터페이스를 구현해야 함
java.lang.AutoCloseable 인터페이스에는 close() 추상 메서드가 포함되어 있다.
예외 처리를 직접 담당하지 않고 throws
를 통해 호출한 쪽으로 예외를 던지고 그 처리를 회피하는 방법이다.
(현재 메서드 안에서 예외 처리를 하지 않고, 현재 메서드를 호출한 메서드로 예외 처리를 떠넘김)
무책임하게 던지는 것은 위험하며, 호출한 쪽에서 다시 예외를 받아 처리하도록 하거나 해당 메서드에서 이 예외를 던지는 것이 최선의 방법인 경우에 사용
1) throws
문을 선언해서 던지거나, 2) catch
문으로 일단 예외를 잡은 후 로그를 남기고 던짐
리턴 타입 메서드명(입력매개변수) throws 예외 클래스명 {
//예외 발생 코드
}
리턴 타입 메서드명(입력매개변수) throws 예외 클래스 A, 예외 클래스 B ... {
//여러 개의 예외 종류가 발생할 수 있는 블록
}
→ 다음과 같이 예외클래스 종류별로 나열하는 것이 일반적이지만, Exception
로 모든 예외를 간단히 떠넘길 수 있다.
예외 회피와 비슷하게 메서드 밖으로 예외를 던지지만, 발생한 예외를 그대로 던지지 않고 적절한 예외로 전환해서 넘기는 방법이다.
이때, 기존 예외를 담아서 중첩 예외로 만드는 것이 좋다.
호출한 쪽에서 예외를 받아서 처리할 때 더 명확하게 인지할 수 있음
주로 강제하는 체크 예외를 언체크 예외인 런타임 예외로 바꾸는 경우에 사용
예외 전환은 2가지 목적으로 사용됨
1) 예외 상황에 대한 적절한 의미를 부여해주지 못하는 경우
2) 예외를 처리하기 쉽고 단순하게 만들기 위해 포장
catch(exception e) {
...
throw 예외 클래스명(e);
}
프로그램을 개발하다보면 자바 표준 API가 제공하는 예외 처리 클래스 이외에 개발하는 프로그램에 따라 다양한 예외 상황이 발생할 수 있다.
이때, 예외 클래스를 직접 정의하여 사용하는 예외를 사용자 정의 예외라고 한다.
throw new 사용자정의예외()
일반 예외 구문
class MyException extends Exception {
MyException() {
}
MyException(String s) { //s는 예외 메시지
super(s); //부모 생성자 호출
}
}
실행 예외 구문
class MyRTException extends RuntimeException {
MyRTException() {
}
MyRTException(String s) { //s는 예외 메시지
super(s); //부모 생성자 호출
}
}
일반 예외 클래스는
Exception
을, 실행 예외 클래스는RuntimeException
을 상속해 정의한다.
일반 예외 구문
MyException me1 = new MyException();
MyException me2 = new MyException("예외 메시지");
실행 예외 구문
MyRTException me1 = new MyRTException();
MyRTException me2 = new MyRTException("예외 메시지");
객체를 생성하는 방법은 일반 예외와 실행 예외가 동일
일반 예외 구문
throw me1; //예외 발생시키기
throw me2;
throw new MyException();
throw new MyException("예외 메시지");
실행 예외 구문
throw me1; //예외 발생시키기
throw me2;
throw new MyException();
throw new MyException("예외 메시지");
- 예외 객체를 던진다 = 실제 자바 가상 머신에게 예외 객체를 만들어 전달한다
- throw로 예외를 던지면 곧바로 예외가 발생하므로 적절한 예외 처리 구문을 반드시 작성해 놓아야 함(해당 메서드 안에서 직접 처리, 예외를 상위 메서드로 전가해 예외 처리)
- throw 키워드는 예외 객체를 던지는 기능을 수행하는 것으로, 예외 객체를 전가하는 throws와 혼동하지 않도록 주의
getMessage()
는 예외가 발생했을 때 생성자로 넘긴 메시지를 문자열 형태로 리턴하는 메서드이다.public String getMessage()
printStackTrace()
는 예외 발생이 전달되는 경로, 즉 예외가 전가된 과정을 한눈에 확인할 수 있는 메서드이다.public void printStackTrace()
📌 try~catch문으로 예외를 잡아놓고 catch를 비워두면 예외가 발생했을 때 원인을 파악하기 어려워 유지보수에 어려움을 겪을 수 있으므로 예외 처리 시 신중해야 한다.
📌 예외 처리를 할 때에는 로그(log)를 남기는 것이 매우 중요하다. 체계적인 로그를 남겨야 오류가 발생했을 때 로그를 보고 오류가 발생하는 코드를 순서대로 따라가며 확인할 수 있고, 원인을 찾을 수 있다.
<이재환의 자바 프로그래밍 입문>
<Do it! 자바프로그래밍 입문>
<Do it! 자바 완전 정복>
https://www.nextree.co.kr/p3239/
https://butter-shower.tistory.com/87
https://qh5944.tistory.com/32
https://madplay.github.io/post/java-checked-unchecked-exceptions
https://europani.github.io/java/2020/05/22/006-exception.html