팀과제를 하다보니 기능을 구현하던 중에서 사용자가 입력을 하는 것이 꼭 있을 것이다.
사용자는 개발자가 원하는 대로 흘러가게 인풋값을 매번 주지는 않을 것이다.
그런 것에 있어 과제에는 예외처리가 필요한 상황이 있는데 예외처리에 대해 적용을 못한게 아쉬어 제대로 알아보고자 한다.
오류( Error) vs 예외 (Exception)
- 오류(Error)는 일반적으로 회복이 불가능한 문제이다.
- 이는 시스템 레벨에서, 또는 주로 환경적인 이유로 발생한다.
- 코드의 문제로 발생하는 경우도 있지만, 일단 발생하는경우 일반적으로 회복이 불가능하다.
- 에러가 발생한 경우 우리는 어떠한 에러로 프로그램이 종료되었는지를 확인하고 대응한다.
- 예외(Exception)는 일반적으로 회복이 가능한 문제이다.
- 회복이 가능하다는 전제는 우리가 “그 예외가 발생할 수 있다는 것을 인지하고, 대응했을 것 이다”.
- 현실적으로 코드레벨에서 할 수 있는 문제상황에 대한 대응은 “예외처리”에 속한다.
예외의 종류
코드실행 관점 에서 예외의 종류
컴파일 에러(예외)
- .java 파일을 .class 파일로 컴파일할때 발생하는 에러
- 대부분 여러분이 자바 프로그래밍 언어의 규칙을 지키지 않았기 때문에 발생한다.
- 예를들어 있지 않은 클래스를 호출한다거나, 접근이 불가능한 프로퍼티나 메소드에 접근한다거나 하는 경우에 발생한다.
- 컴파일 에러가 발생하는 경우 해결 방법은 문법에 맞게 다시 작성하는 것 이다.
런타임 에러(예외)
- 우리가 주로 다루게 될 에러(예외) 이다.
- 문법적인 오류는 아니라서, 컴파일은 잘 되었지만 “프로그램”이 실행도중 맞닥뜨리게 되는 예외 이다.
예외처리 관점 에서 예외의 종류
- 확인된 예외 (Checked Exception)
- 컴파일 시점에 확인하는 예외이다.
- 반드시 예외 처리를 해줘야하는 예외
예외 발생과 Try-catch, finally 문
1. 우리가 예외를 어떻게 정의하고,
2. 예외가 발생 할 수 있음을 알리고,
3. 사용자는 예외가 발생 할 수 있음을 알고 예외를 핸들링하는지
알아보겠다.
- 예외 정의하기
class OurBadException extends Exception {
public OurBadException() {
super("위험한 행동을 하면 예외처리를 꼭 해야합니다!");
}
}
이렇게 본인이 직접 예외클래스를 만들어 예외를 생성할 수 있다.
class OurClass {
private final Boolean just = true;
// 신규 문법 throws!
public void thisMethodIsDangerous() throws OurBadException {
if (just) {
// 신규 문법 throw!
throw new OurBadException();
}
}
}
우리의 메서드가 위험하다고 알리기 위해 (throw, throws)라는 새로운 문법을 사용한다.
throws | throw |
메서드 이름 뒤에 붙어 이 메서드가 어떠한 예외사항을 던질 수 있는지 알려주는 예약어 입니다. | 메서드 안에서, 실제로 예외 객체를 던질 때 사용하는 예약어 입니다. |
여러 종류의 예외사항을 적을 수 있습니다. | 실제로 던지는 예외 객체 하나와 같이 써야 합니다. |
일반 메서드의 return 키워드처럼 throw 아래의 구문들은 실행되지 않고, throw문과 함 께 메서드가 종료됩니다. |
Try-Catch-Finally의 문법을 통해 위험한 메서드를 사용할때 예외를 handling하는 것을 알아보겠다.
public class StudyException {
public static void main(String[] args) {
OurClass ourClass = new OurClass();
try {
// 1. 위험한 메소드의 실행을 "시도" 해 봅니다.
// "시도" 해보는 코드가 들어가는 블럭입니다.
ourClass.thisMethodIsDangerous();
} catch (OurBadException e) {
// 2. 예외가 발생하면, "잡아서" handling 합니다.
// 예외가 발생하는경우 "handling" 하는 코드가 들어가는 블럭입니다.
// 즉 try 블럭 내의 구문을 실행하다가 예외가 발생하면
// 예외가 발생한 줄에서 바로 코드 실행을 멈추고
// 여기 있는 catch 블럭 내의 코드가 실행됩니다.
System.out.println(e.getMessage());
} finally {
// 3. 예외의 발생 여부와 상관없이, 실행시켜야 하는 코드가 들어갑니다.
// 무조건 실행되는 코드가 들어가는 블럭입니다.
System.out.println("우리는 방금 예외를 handling 했습니다!");
}
}
}
용어 정리
- 우리는 방금 예시에서 Checked Exception을 확인하였다.
- 예외가 발생하는 상황을 “인지” 했고, 어떠한 에러인지 “정의” 했다..
- 우리는 메서드를 선언 할 때 예외가 발생하는 위험한 메서드라는 것을 “알렸다 (throws/throw)”.
- 우리가 checked exception을 정의하고, 알렸으니 이 메서드를 사용 할 때 예외처리를 하지 않으면 컴파일 에러가 발생한다.