[Java] 예외(Exception)와 예외처리
# 목적
: 예외(Exception)와 예외처리에 대한 이해
예외처리 란?
: 프로그램 실행 시 발생할 수 있는 오류에 대비하기 위해 프로그램의 비정상 종료를 막고 실행 상태를 유지하는 것
오류의 종류
1. 에러(Error)
- 시스템, 운영체제, JVM의 잘못으로 발생되는 것
- 개발자가 해결할 수 있는 문제가 아님
- 예외처리의 대상이 아님
2. 예외(Exception)
- 개발자의 코딩실수나 사용자의 잘못된 프로그램 사용으로 발생하는 오류
- 예외처리를 통해서 비정상적인 종료 예방 가능
- UncheckedException / CheckedException으로 구분
(1) Unchecked Exception
- RuntimeException 클래스와 그 자식 클래스들
- 주로 개발자의 코딩 실수로 발생되는 오류
- 컴파일러가 예외처리 여부를 체크하지 않음
- 주요 예외 클래스 :
1) RunTimeException
> 모든 UnChecked Exception의 부모 클래스
2) NullPointerException
참조변수의 값이 null인 상태에서 필드나 메소드를 사용할 때 발생하는 예외 클래스
3) ClassCastException
클래스 형변환이 가능하지 않을 때 발생하는 예외 클래스
4) ArithmeticException
나눗셈에서 어떤 값을 0으로 나눌 때 발생하는 예외 클래스
5) IndexOutOfBoundsException
배열, 리스트, 문자열에서 인덱스 범위를 벗어난 위치를 조회했을 때 발생하는 예외 클래스
6) NumberFormatException
Integer.parseInt(s), Double.parseDouble(s) 등을 실행할 때 발생
(2) Checked Exception
- Exception 클래스와 Exception 클래스의 하위 클래스 중에서 RuntimeException 클래스의 하위 클래스가 아닌 예외클래스
- 사용자의 잘못된 사용으로 인해 발생하는 오류
- 컴파일러가 예외처리 구현 여부를 반드시 체크함> 예외처리 관련 코드가 구현되어 있지 않으면 컴파일 오류 발생
> 최신의 라이브러리나 프레임워크에서는 CheckedException의 사용비중이 점점 줄어들고 있음
- 주요 클래스 :
1) Exception
> 모든 Checked Exception의 부모 클래스
2) ClassNotFoundException
> 클래스파일을 찾을 수 없을 때 발생하는 예외클래스
3) IOException
> 읽기/쓰기 하는 도중 오류가 발생했을 때 발생하는 예외클래스
> 네트워크를 통해서 다른 컴퓨터와 데이터 교환 중 오류가 발생했을 때 발생하는 예외클래스
4) FileNotFoundException
> 파일을 찾을 수 없을 때 발생하는 예외클래스
5) SQLException
> 데이터베이스 액세스 작업 중 오류가 발생했을 때 발생하는 예외클래스
📌 예외처리하기
1. try ~ catch 구문으로 예외처리하기
- 직접 예외를 처리
- main 메소드에서 예외일괄처리(catch 여러개)로 사용
👉 작성 예시 :
try {
예외발생이 예상되는 수행문;
예외발생이 예상되는 수행문;
수행문;
} catch(예외클래스타입 변수명) {
} catch(예외클래스타입 변수명) {
} catch(Exception 변수명) {
}
2. throws로 예외처리 위임하기
- 메소드에서 발생하는 예외를 직접 처리하지 않고, 그 메소드를 호출하는 측에서 예외처리를 위임
- 일반 메소드에서 사용
👉 작성 예시 :
public void method() throws 예외클래스명, 예외클래스명, ... {
예외발생이 예상되는 수행문;
예외발생이 예상되는 수행문;
}
* CheckedException이 발생하는 수행문을 메소드에서 실행했을 경우
> throws 키워드를 사용해서 예외처리를 위임
* UncheckedException이 발생하는 수행문을 메소드에서 실행했을 경우
> 예외처리할 필요 없음 (자동으로 발생한 예외가 이 메소드를 호출한 측에게 던져지기 때문에)
3. 사용자정의 예외클래스
1) Checked 사용자정의 예외클래스
: Exception 클래스를 상속받아서 정의
2) Unchecked 사용자정의 예외클래스
: RuntimeException 클래스를 상속받아서 정의* 대부분의 경우 Unchecked 사용자정의 예외클래스를 선호
👉 작성 예시 :
public class MyException extends RuntimeException {
public MyException() {}
public MyException(String message) {
super(message);
}
public MyException(String message, Throwable cause) {
super(message, cause);
}
public MyException(Throwable cause) {
super(cause);
}
}
- Throwable클래스가 에러메세지, 관련 예외를 저장하는 멤버변수를 가지고 있고
초기화하는 생성자도 보유하고 있기 때문에, 부모의 생성자를 통해서 객체를 초기화함
4. 예외의 변환
- 실제 발생한 예외 대신 사용자정의 예외를 발생시키는 것
- throw 키워드 사용 *throw new 예외클래스(오류메세지, 실제발생한예외)
- 여러 종류의 예외를 처리하는 것보다 사용자정의 예외만 처리하도록 하는 것이 목적- 예외를 일괄처리하는 곳에서 처리할 예외의 종류를 줄일 수 있음
👉 작성 예시 :
try {
예외발생이 예상되는 코드 // SQLException 발생이 예상된다고 가정
} catch (SQLException e) {
throw new 사용자정의예외클래스("메세지", e);
}
5. 강제 예외발생
- 업무로직상의 오류가 있는 경우 예외를 강제로 발생시켜서 해당 기능을 호출한 측에게 오류가 발생했음을 알림 ex) 비밀번호 불일치, 잔액부족, 로그인 실패 등
- throw 키워드 사용
- 대부분 UncheckedException에 사용
👉 작성 예시 :
public void login(String id, String password) {
User savedUser = userService.getUser(id);
if (savedUser == null) {
throw new UserNotFoundException("아이디가 존재하지 않습니다.");
}
if (!savedUser.getPassword.equals(password)) {
throw new NotMatchedPasswordException("비밀번호가 일치하지 않습니다.");
}
...
}
6. finally 블록
- 예외 발생 유무와 상관없이 반드시 실행되어야 하는 수행문을 작성하는 블록
- 애플리케이션 실행 중 점유했던 시스템의 자원(리소스)을 해제하는 코드(수행문)을 주로 작성함
- 데이터베이스 액세스 작업에서 트랜잭션처리와 관련된 코드를 작성
👉 작성 예시 :
try {
예외발생이 예상되는 수행문1;
예외발생이 예상되는 수행문2;
수행문3;
} catch (예외클래스 e) {
수행문4;
} catch (예외클래스 e) {
수행문5;
} finally {
수행문6; // 애플리케이션이 점유했던 자원을 해제하는 수행문, 항상 실행
}
< 해당 글은 velog에서 이전하며 옮겨온 글로, 가독성이 좋지 않을 수 있는 점 양해 부탁드립니다. >
🔗 velog 버전 보기 : https://velog.io/@ryuneng2/Java-Exception-예외처리