자바의 예외 처리에 대해 학습하세요.
하드웨어의 오작동 또는 고장으로 인해 응용프로그램에 이상이 생기거나 JVM 실행에 문제가 생겼을 경우 발생한다. 즉 시스템 레벨에서의 문제를 말한다.
ex) VirtualMachineError, OutOfMemoryError, StackOverflowError
사용자의 잘못된 조작 또는 개발자의 잘못된 코딩으로 인해 발생하는 프로그램 오류이다.
예외가 발생하면 프로그램이 종료가 된다는 것은 에러와 동일하지만 예외는 예외처리를 통해 프로그램을 종료하지 않고 정상적으로 실행되도록 해준다.
checked exception,unchecked exception, runtime exception으로 분류할 수 있는데 이를 아래에서 자세히 알아보겠다.
해당 예외는 실행예외로써 애플리케이션을 실행중 발생한다.
NullPointerException
비어있는 객체의 어떠한 행동을 하려할때 발생하는 에러이다. 이러한 예외는 if문을 이용하거나 Optional을 이용하여 예방할 수 있다.
ArrayIndexOutOfBoundsException
배열의 크기 이상 인덱스의 접근하려고 할때 발생하는 에러이다.
이름에서 바로 알 수 있듯이 체크가 가능한 예외이다.
compiler에서 체크가 가능한 에러로 IDE를 사용시 해당 에러 처리를 해주라는 경고가 나온다.
컴파일러가 체크해주지 못하는 에러로 런타임시 발생한다.
이러한 에러는 개발자가 try-catch문으로 예외처리를 해주어야 하는데 컴파일러가 명시해주지 않기 때문에 개발자의 경험 또는 테스트를 통해 예외처리를 진행해야 한다.
보통 프로그램에서 예외가 발생시 종료되지 않고 해당 에러만 처리하고 프로그램은 계속 유지되기를 원할 것이다.
이러한 방법을 제공하기 위해 예외처리를 이용하는데 사용법에 대해 알아보자
try-catch-finally문의 경우 아래와 같은 흐름을 타고 간다.
try문에서는 에러가 발생할 수 있는 코드를 작성하고 해당 코드에서 예외 발생시 catch문의 내용이 실행된다.
그리고 마지막으로 예외여부와 상관없이 finally문이 실행된다.
public static void main(String[] args) {
int[] arr = new int[3];
String str = null;
try {
System.out.println(arr[4]);
System.out.println(str.getBytes());
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("ArrayIndexOutOfBoundsException 발생");
} catch (NullPointerException e){
System.out.println("NullPointerException 발생");
} catch (Exception e) {
System.out.println("모든 에러처리!");
} finally {
System.out.println("종료");
}
}
위 코드의 결과로 아래와 같이 확인되는데 ArrayIndexOutOfBoundsException에 대한 catch문이 실행되는 걸 확인 할 수 있다.
그리고 위의 코드에서 확인해볼점은 다중 catch문이다.
하나의 try문에 여러개의 catch문을 작성할 수 있는데 catch문은 하위 예외 클래스부터 상위 예외클래스 순으로 작성하여야 한다.
왜냐하면 상위의 최상위 클래스인 Exception을 작성하면 해당 catch문에서 모든 예외가 처리될 것이고 아래 catch문은 실행될 일이 없기 때문이다.
그리고 try문에서 여러개의 예외가 발생하는 경우 제일 먼저 발생한 예외를 처리하고 try문을 빠져나가기에 NullpointerException이 발생하지 않는 것을 볼 수 있다.
둘은 비슷하지만 사용하는 용도는 다르다.
먼저 둘은 예외를 발생 지점에서 처리하는게 아닌 해당 메서드를 호출한 부분으로 예외처리에 대한 책임을 넘기는거라 생각하면 된다.
throw는 실제로 Exception을 발생시켜 예외를 던지는 키워드이고
throws는 해당 메서드에서 어떤 예외가 발생할 수 있다는걸 명시적으로 나타낸다.
public static void main(String[] args) throws NullPointerException {
String str = null;
if (str == null) {
throw new NullPointerException();
}
System.out.println(str.getBytes());
}
이미지를 보면 Exception 부모 클래스에 Throwable이 있는데 해당 클래스를 상속 받음으로써 throw문, catch문에 사용할 수 있는 파라미터가 될 수 있는 것이다.
RuntimeException
실행 중에 발생되는 에러이다.
unchecked Exception에 속해있거나 해당 클래스를 상속한 클래스들을 말한다.
예외처리가 강제하지 않기 때문에 개발자가 예외처리에 더욱이 신경 써야한다.
RuntimeException 아닌 Exception
checked Exception으로 예외처리가 강제되기 때문에 IDE를 이용하면 비교적 쉽게 처리가 가능하다
일반 예외로 선언할 경우 Exception을 상속받아 구현한다.
실행 예외로 선언할 경우 RuntimeException을 상속받아 구현한다.
클래스명은 Exception으로 끝나는것을 권장한다.
사용자 정의 예외 클래스 작성 시 생성자는 두 개를 선언하는 것이 일반적이다.(기본 생성자, String타입 매개변수를 갖는 생성자)
public class CustomException extends RuntimeException {
// 1. 매개 변수가 없는 기본 생성자
CustomException() {
}
// 예외 발생 원인(예외 메시지)을 전달하기 위해 String 타입의 매개변수를 갖는 생성자
CustomException(String message) {
super(message); // RuntimeException 클래스의 생성자를 호출
}
}