예외(Exception)
1. 예외(Exceptipn)란?
실생활이나 혹은 코드를 작성하거나, 서비스를 운영할 때 우리가 예상치 못한 방향으로 흘러갈 수 있다.
결국 이러한 예외를 우리가 직접 처리를 해야하는데, 자바에서는 예외(Exception)이라는 것을 던져버린다.
예외는 내부적 혹은 외부적 문제로 인해 발생하는 오류이다. 예외가 발생되면 프로그램은 종료된다는 점에서 에러와 동일하나, 예외는 예외 처리를 통해 프로그램을 종료하지 않고 계속 동작시킬 수 있다.
예시로 null인 객체에 메소드를 호출하거나, 5칸 짜리 배열이 있는데, 6번째 인덱스 값을 출력하라던지 등이 여기에 포함된다.
자바를 맛 본 사람이라면 대충 어떤 방식으로 예외 처리가 진행되는지 알 것이다. = try - catch
다음과 같은 코드가 있다고 해보자.
main() 메소드에서 arrayOutofBounds()라는 메소드를 호출하도록 되어있는데, 메소드를 들여다 보면 5칸짜리 1차원 배열을 만들었다. 근데 출력에서 6번째 칸을 출력하라고 하네??? (5번 방까지 있는데 6번방을 출력하라고??) - 당연히 컴파일이 될 수가 없다.
우리가 예상한 것처럼 실행하면 다음과 같은 메세지를 보여줄 것이다.
예외명을 보면 ArrayIndexOutofBoundsException 이라는 것이 발생했는데 "배열의 범위 밖에 있는 위치를 요청한 예외"이다.
결국 예외를 발생하지 않도록 하는 개발이 가장 우선이겠지만, 우리도 사람인지라 놓치는 부분이 생기기 마련이다.
이전의 코드에서 arrayOutofBounds()를 주석처리하고 같은 기존의 메소드를 활용해 새로운 메소드를 만들었다.
아래의 코드를 실행하면 아까 발생했던 예외가 발생할까?
해당 코드를 작성해서 실행해보면 정상적으로 컴파일 되고 실행도 정상적으로 된다.
비록 출력되는 메세지가 없어서 어 뭐야 이게 제대로 된거야? 할 수 있겠지만, 실제로 예외는 발생한 것으로, 해당 코드에 추가로 출력문을 넣어서 확인해볼 수 있다.
아래의 코드를 실행하면 어떻게 출력이 될까? 동일하게 공백이 출력이 될까? 혹은 군계일학 이라는 사자성어가 출력이 될까?
실제로 런해보면 위와 동일하게 아무것도 출력이 되지 않는다.
자바의 try-catch는 try 블록 안에서 예외가 발생되면 그 이하의 문장은 실행되지 않고 바로 catch 블록으로 넘어간다.
위의 코드에서 주석처리 된 각골난망과 안분지족을 주석해제하고 런해보면 결과는 다음과 같다.
결국 try-catch에서 예외가 발생하지 않을 경우에는 try속 모든 문장이 실행되고 try-catch 이후의 문장이 실행된다.
try-catch에서 예외가 발생할 경우 try내에서 예외가 발생한 이후의 문장들은 실행되지 않으며, catch내의 문장은 반드시 실행되고, 동일하게 try-catch 이후의 문장이 실행된다.
이렇게 예외처리를 할 때 하기 쉬운 실수가 있다. 코드를 통해 이해 해보자.
이러한 코드가 있는데 보면 예외가 발생하고 catch 블록에서는 intArray의 길이를 출력하고, 마지막으로 또 출력을 하게 되어있다. 이 코드를 실행하면 어떻게 결과가 나올까? 우리가 생각한 것처럼 try에서 발생한 예외가 catch로 넘어와서 intArray[5]의 길이인 5를 출력하고, 이 코드는 실행 중 입니다. 라고 분명히 출력될 것이다.
그런데 만약에 이 코드에서 int[] intArray= new int[5]를 try 블록 속으로 넣으면 어떻게 될까??
결국 일반적으로 catch 문장에서 사용할 변수에 대해서는 try 앞에 선언해야 한다. (지역, 전역변수, 변수의 범위)
코드를 아래와 같이 수정해보자.
intArray 배열을 null로 만들어 버리고, try에서 intArray 배열을 5칸으로 만들어 줬다.
실행 결과는?
의문을 가질 수 있는데 이유는 다음과 같다.
예외가 발생하여 catch 블록이 실행된다고 해서 try 블록 내의 실행된 모든 문장이 무시 되는 것은 전혀 아니다.
(결국 예외는 intArray[5]를 호출하는 순간 발생한다는 의미)
위의 코드와 달라진 점을 찾으면 finally가 추가되었다.
실행하면 5, 끝, 이 코드는 실행 중입니다 가 출력 될 것인데, 이처럼 finally 블록은 예외 발생 여부와 상관 없이 실행된다.
finally 블록은 코드의 중복을 피하기 위해 반드시 필요하다. (그러나 생략 가능)
앞서 계속 예외처리에 있어서 가장 기본적인 것들을 정리하고 있다. 위 코드를 보면 catch(Exception e)가 있는데, 이 소괄호에는 예외의 종류를 명시한다. (항상 Exception e를 사용하는 것이 아님..)
예외에는 3가지 종류가 있다.
1. checked exception
2. error
3. runtime exception 혹은 unchecked exception
하지만 예외를 구분할 때 2번과 3번을 제외한 모든 예외는 checked exception 이다.
1.Error
해당 에러는 자바 프로그램 밖에서 발생한 예외를 말한다.
자바 프로그램에서 오류가 발생했을 때, 오류의 이름이 error로 끝나면 에러이고, Exception으로 끝나면 예외이다.
error와 exception으로 끝나는 오류의 가장 큰 차이는 발생한 위치에 있다. 더 큰 차이는 프로그램의 중지에 있다. Error는 프로세스에 영향을 주고, Exception은 쓰레드에만 영향을 준다.
2. runtime exception
런타임 예외는 예외가 발생할 것을 미리 감지하지 못했을 때 발생하는데 , 이 런타임 예외에 해당하는 모든 예외들은 RuntimeException을 확장한 예외들이다. 이 예외를 묶어주지 않는다고 해서 컴파일 할 때 예외가 발생하지 않는다. 하지만 실행시에는 발생할 가능성이 있다. 이러한 예외들을 런타임 예외라고 부른다. 컴파일시에 체크를 하지 않기 때문에 위에서 말한 unchecked exception이라고도 한다.
여기서 Exception을 확장한 클래스들이 Checked예외이다.
Exception과 Error 클래스는 Throwable 클래스를 상속받아 처리하도록 되어 있는데, 그래서 Exception이나 Error를 처리할 때 Throwable로 처리해도 된다.
Throwable 클래스 속에는 다양한 메소드가 존재하는데, 그 중 많이 사용하는 몇 메소드가 존재한다
1. getMessage()
이 메소드는 예외 메세지를 String 형태로 제공받는다. 예외가 출력되었을 때 어떤 예외가 발생되었는지 확인할 때 유용하게 사용한다.
2. toString()
위와 동일하게 예외 메세지를 String 형태로 제공 받는데, 위의 메서드보다 좀 더 자세하게 제공한다.
3. PrintStatckTrace()
이 메소드는 가장 첫 줄에는 예외 메세지를 출력하고, 두 번째 줄부터는 예외가 발생하게 된 메소드들의 호출 관계(스택 트레이스)를 출력해준다.
앞서 발생한 예외에 대해서 처리하는 법에 대해서 정리했는데, 자바에서는 예외를 발생시킬 수 있다(예외를 던지다). 바로 throws이다.
보통 예외를 처리할 때 try-catch 블록에서 해결하는 경우가 많은데, 경우에 따라서 메소드를 호출한 곳으로 예외를 넘길 수 있다. 이때 사용하는 키워드가 throws이다.
throws는 메소드 구현부 맨 마지막에 선언하며, 예외가 발생했을 때 try-catch로 묶어주지 않아도 그 메소드를 호출한 메소드로 예외 처리를 위임하는 것이라 문제가 발생하지 않는다.
- 메소드를 선언할 때 매개 변수 소괄호 뒤에 throws라는 예약어를 적어 준 뒤 예외를 선언하면 해당 메소드에서 선언한 예외가 발생했을 때 호출한 메소드로 예외가 전달된다.
- try 블록 내에서 예외를 발생시킬 경우에는 throw라는 예약어를 적어 준 뒤 예외 객체를 생성하거나, 생성되어있는 객체를 명시해준다.(throw한 예외 클래스가 catch 블록에 선언되어 있지 않거나, throws 선언에 포함되어 있지 않으면 컴파일 에러가 발생한다.)
- catch 블록에서 예외를 throw 할 경우에도 메소드 선언의 throws 구분에 해당 예외가 정의되어 있어야 한다.
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
20220-11-26 추가
위에선 예외처리의 기본적인 내용을 학습하고, 정리했다.
'Language > Java' 카테고리의 다른 글
자료형과 BigDecimal 그리고 소수점(부동, 고정) (0) | 2022.05.22 |
---|---|
String 과 JVM (0) | 2022.05.22 |
인터페이스와 추상클래스 그리고 Enum (0) | 2022.05.14 |
람다식(Lambda)과 함수형 인터페이스(fuctional interface) (0) | 2022.01.23 |
추상 클래스(abstract class)와 인터페이스(interface) (0) | 2022.01.23 |