본문 바로가기
Language/Java

자바 9주차 : 예외 처리

by CleanCoder 2021. 2. 14.

 

목표

자바의 예외 처리에 대해 학습하세요.

학습할 것 (필수)

  • 자바에서 예외 처리 방법 (try, catch, throw, throws, finally)
  • 자바가 제공하는 예외 계층 구조
  • Exception과 Error의 차이는?
  • RuntimeException과 RE가 아닌 것의 차이는?
  • 커스텀한 예외 만드는 방법

 

1. 자바에서 예외 처리 방법 (try, catch, throw, throws, finally)

 

 try, catch, finally는 예외가 발생한 메소드 내에서 직접 처리하고자 할 때 작성되는 코드이다. 실행 예외는 컴파일러가 체크해주지 않으므로 예외 처리 코드를 개발자의 경험을 토대로 작성해야 한다. try-catch-finally 블록은 생성자 내부와 메소드 내부에서 작성되어 일반 예외와 실행 예외가 발생할 경우 예외 처리를 할 수 있도록 도와준다.

 

 

try 블록은 예외가 발생할 가능성이 있는 범위를 지적하는 블록이다. try 블록은 최소한 하나의 catch 블록이 있어야 하며, catch 블록은 try 블록 다음에 위치한다. 여러 예외가 발생하게되면 하나의 try문에 catch블록을 여러 개 사용하여 해결한다. try 블록과 catch 블록에서 return문을 사용하더라도 finally 블록은 항상 실행 처리된다.

try{
	// 예외 발생 가능성이 있는 코드
}catch(예외 타입 1 매개변수명){
	// 예외타입1의 예외가 발생할 경우 처리 코드
}catch(예외 타입 2 매개변수명){
	// 예외타입2의 예외가 발생할 경우 처리 코드
}finally{
	// 항상 처리할 필요가 있는 코드
}

 

다중 catch문을 작성할 때 주의할 점상위 예외 클래스가 하위 예외 클래스보다 아래쪽에 위치하지 않으면 상위 예외 클래스를 처리하고 하위 예외 클래스의 처리가 이루어지지 않는다는 점이다.

try{

}catch(Exception e){
	//상위 클래스 예외 처리
}catch(ArrayIndexOutOfBoundsException e){
	//하위 클래스 예외 처리 (처리 되지 않음)
}

 

자바 7부터는 멀티 catch 기능이 추가되었다. 예외를 | 로 연결하여 동일하게 처리될 예외들을 작성할 수 있다.

try{

}catch(ArrayIndexOutOfBoundsException | NumberFormatException e){
	//예외 처리 1
}catch(Exception e){
	//예외 처리 2
}

 

자동 리소스 닫기

 

 자바 7에서 추가된 try-with-resources를 사용하면 예외 발생 여부와 상관없이 사용했던 리소스 객체(각종 입출력 스트림, 서버 소켓, 소켓, 각종 채널)의 close() 메소드를 호출해서 안전하게 리소스를 닫아준다.

 

여기서 리소스란 데이터를 읽고 쓰는 객체라고 생각하면 편하다.

ex) 파일의 데이터를 읽는 FileInputStream 객체와 파일에 쓰는 FileOutputStream

 

try(FileInputStream fis = new FileInputStream("file.txt")){

} catch(IOException e){

}

try 블록이 정상적으로 실행을 완료했거나 도중에 예외가 발생하게 되면 자동으로 FileInputStream의 close() 메소드가 호출된다. try {} 예외가 발생하면 우선 close()로 리소스를 닫고 catch 블록이 실행되는 구조를 가진다.

 

try-with-resources 사용을 위해서는 리소스 객체는 java.lang.AutoCloseable 인터페이스를 구현하고 있어야 한다. 이 인터페이스에는 close() 메소드가 정의되어 있어 불러오게 되는 것이다.

 

AutoCloseable interface

public interface AutoCloseable{
	void close() throws Exception;
}

 

 

예외 넘기기 (throws, throw)

 

throws는 메소드 선언부 끝에 작성되어 메소드에서 처리하지 않은 예외를 호출한 곳으로 떠넘기는 역할을 한다. throws 키워드 뒤에는 떠넘길 예외 클래스를 쉼표로 구분해서 나열해주면 된다.

리턴타입 메소드명(매개변수,...) throws 예외클래스1, 예외클래스2, ...{
}

모든 예외를 넘기기 위해서는 Exception을 적어주면 된다.

리턴타입 메소드명(매개변수,...) throws Exception{
}

 

 

throw

 

 인위적으로 예외를 발생시킬 때 사용할 수 있는 예약어 ⇒ throw

개발자가 의도하진 케이스에 대해 임의로 예외를 발생시킬 때 사용되며, 특정 예외를 만났을 때 더욱 구체적인 예외로 처리하고자 할 때에도 사용된다.

public void method() throws Exception{
	throw new Exception("메시지");
}

 

2. 자바가 제공하는 예외 계층 구조

 

모든 예외의 계층 구조

 

 

  • 예외와 오류는 모드 Throwable 클래스의 하위 클래스인데, 에러는 보통 시스템 리소스 문제로 발생하게 되는데, 애플리케이션 리소스 문제를 알면 안 되기도 한다. Error는 보통 시스템 충돌, 메모리 부족 이 있고,
  • 예외는 컴파일 시간과 런타임 시 발생하는 게 대부분이다. 주로 개발자가 작성한 코드로 발생한다.

Exception과 Error 모두 프로그램이 종료되는 공통점이 있는데 Exception은 런타임 에러일 때, 예외처리가 가능하다.

모든 예외 클래스는 java.lang.Exception에 저장되어 있다. 일반 예외와 실행 예외 모두 다음의 패키지 구성 요소를 가진다.

 

일반 예외 (Exception) : 일반 예외와 실행 예외 클래스를 구별하는 방법은 예외 Exception을 상속받지만, RuntimeException은 상속받지 않음

 

실행 예외 (Runtime Exception) : 실행 예외는 RuntimeException을 상속받는다. 물론, 표에서 보다시피 Rumtime Exception이 java.lang.Exception을 상속받지만, JVM은 RuntimeException 상속 여부를 보고 실행 예외를 판단한다.

 

 

3. Exception과 Error의 차이는?

 

Exception과 Error는 다음의 차이를 가지고 있다.

 

Error

컴퓨터 하드웨어의 오동작 또는 고장으로 인해 응용프로그램 실행 오류가 발생하는 것을 자바에서는 Error(에러)라고 한다. 에러는 JVM 실행에 문제가 생겼다는 것으로, JVM 위에서 실행되는 프로그램이 결국 실행 불가능하게 된다. 

 

Exception

예외란 사용자의 잘못된 조작 또는 개발자의 잘못된 코딩으로 발생하는 프로그램 오류이다. 예외가 발생하면 프로그램은 곧바로 종료된다는 점에서 에러와 비슷하다. 그러나 예외는 예외 처리(Exception Handling)를 통해 정상 실행 상태가 유지되도록 할 수 있다.

 

 

4. RuntimeException과 RE가 아닌 것의 차이는?(Checked Exception & Unchecked Exception)

 

 Checked Exception예외처리를 하지 않을 경우 컴파일 에러를 발생시키도록 하여, 반드시 예외처리를 해야 하는 Exception을 말한다.

 

Unchecked Exception처리하지 않더라도, 컴파일 에러가 발생하진 않지만 발생할 수 있는 예외들로 RuntimeException 클래스를 상속하는 모든 Exception 클래스가 Unchecked Exception으로 예외처리를 강제화하지 않는다. (Error 도 Unchecked Excpetion이다.)

 

  Checked Exception Unchecked Exception
예외 처리 반드시 예외처리를 해야함 예외처리를 강제하지 않음
확인 시점 컴파일 타임 런타임

 

5. 커스텀한 예외 만드는 방법

 

예를 들어 은행 잔고 출금 부족과 같은 예외는 자바 표준 API에 존재하지 않기에 직접 작성해야 한다.

이와 같이 애플리케이션 서비스와 관련된 예외를 애플리케이션 예외(Application Exception)라고 한다. 다른 말로는 개발자가 직접 정의하므로 사용자 정의 예외라고도 한다.

 

사용자 정의 예외 클래스는 컴파일러가 체크하는 일반 예외로 선언할 수도 있고, 컴파일러가 체크하지 않는 실행 예외로 선언할 수도 있다. 일반 예외로 선언할 경우 Exception을 상속하면 되고, 실행 예외로 선언할 경우에는 RuntimeException을 상속하면 된다.

 

사용자 정의 예외 클래스 이름은 Exception으로 끝나는 것이 좋다. 

사용자 정의 예외 클래스도 필드, 생성자, 메소드 선언들을 포함할 수 있지만 대부분 생성자 선언만을 포함한다. 생성자는 두 개를 선언하는 것이 일반적인데, 하나는 매개 변수가 없는 기본 생성자이고, 다른 하나는 예외 발생 원인(예외 메시지)을 전달하기 위해 String 타입의 매개 변수를 갖는 생성자이다. String 타입의 매개 변수를 갖는 생성자는 상위 클래스의 생성자를 호출하여 예외 메시지를 넘겨준다.

 

사용자 정의 예외 클래스

public class BalanceInsufficientException extends Exception{
	public BalanceInsufficientException(){}
	public BalanceInsufficientException(String message){
		super(message);
	}
}

BalanceInsufficientException은 Exception을 상속하기 때문에 컴파일러에 의해 체크되는 예외가 된다. 소스 작성 시 try-catch 블록으로 예외 처리가 필요하다.

 

'Language > Java' 카테고리의 다른 글

자바 11주차 : Enum  (0) 2021.03.05
자바 10주차 : 멀티쓰레드 프로그래밍  (0) 2021.03.05
JAVA 8주차 : 인터페이스  (0) 2021.02.14
JAVA 7주차 : 패키지  (0) 2021.02.14
JAVA 6주차 : 상속  (0) 2021.02.13

댓글