시스템에 비정상적인 상황이 생겼을 때 발생하는 것이 오류이다.
오류는 개발자가 예측할 수 없는 시스템 레벨에서 발생하는 심각한 오류로 오류에 대한 처리를 신경 쓰지 않아도 된다.
→ 시스템에 변화를 주어 문제를 처리해야하는 경우가 일반적
개발자가 구현한 로직에서 발생하는 것이 예외이다.
예외는 개발자가 미리 예측하여 처리할 수 있기 때문에 예외의 종류를 구분하고 그에 따른 처리 방법을 명확히 알고 적용하는 것이 중요하다.
오류와 예외는 최상위 클래스인 오브젝트와 그 하위 클래스인 Throwable 클래스를 상속받는다.
예외는 많은 자식클래스를 가지고 있는데 그 중 RuntimeException은 CheckedException과 UncheckedException으로 구분하는 기준이 된다.
CheckedException | UncheckedException | |
---|---|---|
처리여부 | 반드시 예외처리 | 명시적 처리 강제x |
확인시점 | 컴파일 단계 | 실행단계 |
예외 발생시 트랜잭션 처리 | 롤백함 | 롤백안함 |
대표 예외 | IOException SQLException | RuntimeException 하위 |
0으로 나누는 경우가 발생
↪ if문으로 나누는 수가 0인지 확인 후 연산
배열의 인덱스 범위를 넘어서 참조하는 경우
↪ array.length를 이용해 배열의 길이 확인
배열의 크기를 음수로 지정한 경우 발생
↪ 배열의 크기는 0보다 커야한다.
Cast연산자를 사용할 때 타입 오류
↪ instanceof 연산자를 이용하여 객체의 타입을 확인후 연산
null인 참조변수로 객체 멤버를 참조할 때 발생
↪ 객체 사용전 참조변수가 null인지 확인
try{
///예외가 발생할 가능성이 있는 코드
Scanner sc = new Scanner(System.in); //만약 여기서 Scanner클래스를 열어줬다면
.................. ; << 1. 여기서 예외가 발생했을 때
.................. ; << 2. 예외 발생한 곳 아래는 실행하지 않고,
}
catch(예외클래스 e) {
e.printStackTrace(); //이거는 꼭 쓰자 왜냐면 무슨 예외가 발생했는지는 알아야하기 때문
예외 처리; << 3. catch문에서 예외처리
}
finally {
///무슨 일이 있든 항상 실행
try{ //여기서 Scanner클래스를 닫아줘야한다.
if(sc!= null)sc.close();
} catch(IOExceptione) {}
}
try{
// 예외 1 발생위치
// 예외 2 발생위치
}
catch(예외1을 잡는 곳){
}
catch(예외2를 잡는 곳){
}
다중 catch문을 작성할 때는 상위 예외 클래스가 하위 예외 클래스보다 밑에 위치하게 작성해야한다.
예를 들어
try{
}
catch(Exception e){
}
catch(NullPointerException e){
}
Exception이 NullPointerException보다 상위 클래스이기 때문에 먼저 처리되어 NullPointerException은 사용되지 않는다..!
자바 7에서 추가된 기능으로 finally에서 닫아주는 처리 try문에서 자동으로 처리해준다!
try (Scanner sc = new Scanner(System.in)){
...........;
} catch (NullPointerException e){}
} catch (Exception e){e.printStackTrace();}
메소드를 호출한 곳으로 예외처리를 떠넘기는 방법
public void ThrowTest1(){
try {
ThrowTest2(); // throws가 붙은 ThrowTest2는 반드시 try문 안에서 실행
// ThrowTest2가 떠넘긴 예외를 아래 catch문을 통해 처리
}
catch (NegativeArraySizeException e) {
System.out.println("배열의 크기를 양수로 지정해주세요.");
}
public void ThrowTest2() throws NegativeArraySizeException {
int[] a = new int[-4];
}
Exception 클래스를 상속받아서 사용자가 직접 예외 클래스를 작성하는 것이다.
public class UserException extends Exception{ //Exception클래스 상속
public UserException() {}
public UserException(String str) {
super(str);
}
}
public class UserExceptionTest{
public void method() throws UserException{
throw new UserException("UserException"); //throw new 예외클래스명()으로 생성
}
}
📌Q. NullPointerException같은 하위 클래스가 상위 클래스인 Exception 뒤에 오면 Exception에 막혀서 NullPointerException은 실행이 되지 않는다고 하는데 그러면 Exception으로 통합해서 사용하면 안되는 이유가 있나요?? 예외마다 그 예외에 맞는 Exception을 catch해주어야하나요?
A. Exception마다 하는일이 따로 있기 때문에 각각 처리해주는 것이 바람직