SHUSTORY

14-2 예외 처리하기 본문

프로그래밍/JAVA

14-2 예외 처리하기

어서오시우 2023. 3. 16. 23:31
728x90

try-catch문

예외를 처리하는 가장 기본 문법인 try-catch문의 형식은 다음과 같다.

try-catch문

try 블록에는 예외가 발생할 가능성이 있는 코드를 작성한다.

만약 try 블록 안에서 예외가 발생하면 바로 catch 블록이 수행된다.

catch문의 괄호 ( ) 안에 쓰는 예외 타입은 예외 상황에 따라 달라진다.

 

try-catch문 사용하기

간단한 배열 예제로 예외가 발생하는 상황을 만들고 그에 따른 예외 처리를 해보자.

다음은 요소가 5개인 정수형 배열을 만들고 총 6개의 숫자를 배열에 넣었을 때 발생하는 예외 상황이다.

 

예제01_try-catch문 사용하기

 

RuntimeException의 하위 클래스인 ArrayIndexOutOfBoundsException으로 처리하였다.

이 클래스는 예외 처리를 하지 않아도 컴파일 오류가 나지 않기 때문에

프로그래머가 직접 예외 처리를 하지 않으면 예외가 잡히지 않아서 예외가 발생하는 순간에 프로그램이 갑자기 멈춘다.

그러므로 예외가 발생하는 순간 프로그램이 비정상 종료되지 않게 하기 위해 예외 처리를 해주어야 한다.

 

비정상 종료 되는 경우 "프로그램 종료" 출력문이 출력되지 않는다.

하지만 예외를 catch블록에서 처리하기 때문에 출력문이 정상적으로 출력되며, 프로그램이 정상 종료된다.

이처럼 예외 처리는 프로그램이 비정상 종료되는 것을 방지할 수 있으므로 매우 중요하다.

 

 

컴파일러에 의해 예외가 체크되는 경우

위 예제는 예외 처리를 하지 않아도 컴파일 오류가 나지 않지만, 자바에서 제공하는 많은 예외 클래스들은 컴파일러에 의해 처리된다. 이 경우 자바에서는 예외 처리를 하지 않으면 컴파일 오류가 계속 남게 된다.

 

파일 입출력에서 발생하는 예외 처리하기

자바에서 파일을 읽고 쓰는 데 스트림 객체를 사용한다.

다양한 스트림 종류 중 파일에서 데이터를 바이트 단위로 읽어 들이는 FileInputStream을 사용하여

예외를 처리해야 하는 파일 입출력 관련 예제를 살펴보자.

 

예제02

 

5행에서 a.txt. 파일에서 데이터를 읽어 들이기 위해 스트림 객체를 생성했는데, 오류가 발생했다.

그 이유는 'FileNotFoundException'이 처리되지 않았기 때문이다.

예제02_오류

커서를 올려보면 위 두 가지 옵션이 있는 것을 볼 수 있다.

a.txt. 파일을 열어 읽으려고 FileInputStream 클래스를 생성하였는데, 이 경우 a.txt 파일이 존재하지 않는 오류가 발생할 수 있다는 의미이다. 읽고자 하는 파일이 없을 경우 JVM에서 FileNotFoundException 예외 클래스가 생성된다.

따라서 위 오류 메시지는 이러한 예외 상황에 대비한 예외 처리를 해야 한다는 뜻이다.

 

예제03_예제02 try-catch

 

먼저 try-catch 옵션을 클릭하면, 예외 발생 위험이 있는 코드가 try 블록으로 감싸지고, 해당 블록이 먼저 수행된 뒤

이 코드에서 예외가 발생하면 catch 블록을 수행한다.

try문으로 감싸진 부분에서 발생할 수 있는 예외는 FileNotFoundException이고 변수 이름 e로 선언되었다.

그리고 어디에서 예외가 발생했는지 따라 가는 printStackTrace( ) 메서드가 호출되었다.

이를 통해 a.txt 파일이 없지만 코드 실행 결과 비정상 종료되지 않도록 코드를 구현하였다.

 

예제03_코드 완성 후 실행

 

예외가 발생했을 때 FileNotFoundException e의 toString( ) 메서드가 호출되도록 코드를 작성하였다.

출력 결과의 첫 번째 줄은 e의 출력 내용이다.

예외 처리 후에도 프로그램이 계속 수행되었음을 출력 결과 두번째 줄을 통해 확인할 수 있다.

 

이처럼 예외 처리를 통해 프로그램의 예외 상황 자체를 막진 못하더라도

예외 상황을 알리는 메시지를 볼 수 있고, 프로그램이 비정상 종료되지 않고 계속 수행되도록 할 수 있다.

 

 

try-catch-finally문

* 리소스(resource)란 시스템에서 사용하는 자원으로 파일, 네트워크, 데이터베이스 연결 등을 의미한다.

프로그램에서 사용한 리소스는 프로그램이 종료되면 자동으로 해제된다.

하지만 끝나지 않고 계속 수행되는 서비스 같은 경우 리소스를 여러 번 반복해서 열기만 하고 닫지 않을 경우

시스템에서 허용하는 자원에는 한계가 있기 때문에 문제가 발생한다.

따라서 사용한 시스템 리소스는 사용 후 반드시 close( ) 메서드로 닫아 주어야 한다.

 

예제04_close( ) 메서드

 

현재는 14행의 try 블록에서만 파일 리소스를 닫았다.

그런데 프로그램이 정상적으로 종료된 경우나, 비정상 종료된 경우에도 파일 리소스를 닫아야 한다.

따라서 try 블록뿐 아니라 catch 블록에서 close( ) 메서드를 사용해야 한다.

 

만약 try 블록 안에서 발생할 수 있는 예외 상황이 여러 개라면 catch 블록을 예외 상황 수만큼 구현해야 한다.

그런데 한번 열어 놓은 리소스를 해제하는 코드를 try-catch-catch... 각 블록에 모두 작성해야 한다면 번거로울 것이다.

이때 사용하는 블록이 finally이다.

일단 try 블록이 수행되면 finally 블록은 try나 catch문에 return문이 있는 경우를 포함하여 어떤 경우에도 반드시 수행된다.

finally 사용 형식

 

예제05_예제04 finally 블록 사용하여 구현 후 실행

 

우선 입력받은 파일이 없는 경우에 대해 try-catch문을 사용해 FileNotException 예외 처리를 하였다.

예외 출력 후 14행에서 강제 return 하였다.

그 결과 finally 블록이 수행되어 "항상 수행된다." 라는 문장이 출력된 것을 볼 수 있다.

이 finally 블록에서 파일 리소스를 닫는 코드를 구현하였다.

fis.close( ) 문장에서도 예외가 발생할 수 있으므로 예외 처리를 해야 한다.

 

 

try-with-resources문

시스템 리소스를 사용하고 해제하는 코드는 다소 복잡하다.

자바 7부터 try-with-resources문을 제공하여 close( ) 메서드를 명시적으로 호출하지 않아도

try 블록 내에서 열린 리소스를 자동으로 닫도록 만들 수 있다.

try-with-resources 문법을 사용하려면 해당 리소스가 AutoCloseable 인터페이스를 구현해야 한다.

 

AutoCloseable 인터페이스에는 close( ) 메서드가 있고 이를 구현한 클래스는 close( )를 명시적으로 호출하지 않아도

close( ) 메서드 부분이 호출된다.

FileInputStream 클래스는 Closeable과 AutoCloseable 인터페이스를 구현하였기 때문에 자바 7부터는 try-with-resources 문법을 사용하면 FileInputStream 클래스 사용 시 close( )를 명시적으로 호출하지 않아도 close( ) 메서드가 호출된다.

* 이외에도 네트워크와 데이터베이스 관련 클래스도 AutoCloseable 인터페이스를 구현하고 있다.

 

AutoCloseable 인터페이스

AutoCloseable 인터페이스를 직접 구현한 클래스를 만들고

프로그램이 정상적으로 수행되었을 때와 예외가 발생했을 때 각각 close( ) 메서드 부분이 잘 호출되는지 살펴보자.

 

예제06 / 예제07_AutoCloseable 인터페이스 구현

 

AutoCloseable 인터페이스는 반드시 close( ) 메서드를 구현해야 한다.

시스템 리스소인 경우 파일 스트림을 닫거나 네트워크 연결을 해제하는 코드를 작성해야겠지만,

여기에서는 close( ) 메서드가 제대로 호출되는지 알아보기 위해 출력문만 남긴다.

 

try-with-resources문

try-with-resources문을 사용할 때 try문의 괄호( ) 안에 리소스를 선언한다.

리소스를 여러 개 생성해야 한다면 세미콜론( ; )으로 구분한다.

 

예제06

 

예제06에서는 예외가 발생하지 않고 정상 종료되는데 출력 결과를 보면 close( ) 메서드가 호출된 것을 볼 수 있다.

 

예제07

 

throw new Exception( ) 문장을 사용하면 프로그램에서 강제로 예외를 발생시켜 catch 블록이 수행되도록 구현할 수 있다.

출력 결과를 보면 리소스의 close( ) 메서드가 먼저 호출되고 예외 블록 부분이 수행되는 것을 볼 수 있다.

 

이처럼 try-with-resources문을 사용하면 close( ) 메서드를 명시적으로 호출하지 않아도 항상 리소스가 잘 해제된다.

 

 

향상된 try-with-resources문

자바 9부터는 try문의 괄호 안에서 외부에서 선언한 변수도 사용 가능하게 되었다.

다음은 예제06을 향상된 try-with-resources문으로 바꾸어 구현한 것이다.

 

예제08_예제06 변형

'프로그래밍 > JAVA' 카테고리의 다른 글

14-4 사용자 정의 예외  (0) 2023.03.17
14-3 예외 처리 미루기  (0) 2023.03.17
14-1 예외 클래스  (0) 2023.03.16
13-2 람다식  (0) 2023.03.14
13-1 내부 클래스  (0) 2023.03.13