자바의 예외 처리에 대해 학습하세요.
- 자바에서 예외 처리 방법 (try, catch, throw, throws, finally)
- 자바가 제공하는 예외 계층 구조
- Exception과 Error의 차이는?
- RuntimeException과 RE가 아닌 것의 차이는?
- 커스텀한 예외 만드는 방법
Exception과 Error의 차이는?
구분 | Error | Exception |
타입 | 확인되지 않은 유형으로 분류 | Checked와 Unchecked로 분류 |
패키지 | java.lang.error | java.lang.Exception |
복구 | 불가 | 가능 |
발생 | 컴파일 시 발생할 수 없음 | 런타임 & 컴파일 시 발생 |
예 | OutOfMemoryError, IOError | NullPointerException, SqlException |
Error
- 시스템 레벨에서 발생
- 개발자가 미리 예측하여 처리할 수 없기 때문에, 어플리케이션단에서 오류에 대한 처리를 신경쓰지 않아도 된다.
Exception
- 개발자가 구현한 로직에서 발생
- 발생상황을 미리 예측하여 처리할 수 있다.
- 예외를 구분하고 그에 따른 처리방법을 명확히 알고 적용하는 것이 중요하다.
자바가 제공하는 예외 계층 구조
- 모든 예외 클래스는 Throwable 클래스를 상속받고 있다.
- Throwable는 최상위 클래스 Object의 자식이다.
- RuntimeException은 CheckedException과 UnCheckedException을 구분하는 기준이다.
RuntimeException과 RE가 아닌 것의 차이는?
Checked Exception과 Unchecked(Runtime) Exception
구분 | Checked Exception | Uncehcked Exception |
처리여부 | 반드시 예외를 처리해야 한다. try/catch 구문으로 감싸거나 throw로 던져야 한다. |
명시적인 처리를 강제하지 않는다. |
확인시점 | 컴파일 시점 | 런타임 시점 |
대표적인 예외 | Exception을 상속하는 하위 클래스 중 Runtime Exception을 제외한 모든 예외 - IOException - SQLException |
Exception을 상속한 하위 클래스 중 Runtime Exception 하위예외 - NullPointerException - IllegalArgumentException - IndexOutOfBoundException |
자바에서 예외 처리 방법 (try, catch, throw, throws, finally)
try-catch 문
- try 블럭에는 여러 catch 블럭이 올 수 있으며 발생한 예외의 종류와 일치하는 단 한개의 catch 블록만 수행
- printStackTrace() : 예외 발생 당시의 호출스택에 있었던 메서드 정보와 예외 메시지를 화면에 출력한다
- getMessage() : 발생한 예외클래스의 인스턴스에 저장된 메세지를 얻을 수 있다.
try {
// 예외가 발생할 가능성이 있는 코드
} catch (Exception1 e1) {
// Exception1이 발생했을 때, 이를 처리하기 위한 코드
} catch (Exception2 e2) {
// Exception2가 발생했을 때, 이를 처리하기 위한 코드
} catch (ExceptionN eN) {
// ExceptionN이 발생했을 때, 이를 처리하기 위한 코드
}
Multicatch block
- 자바 7부터 여러 catch block을 하나로 합칠 수 있다.
public static void main(String[] args) {
ThrowException ex = new ThrowException();
try {
ex.loadClass("b.txt", "java.lang.string");
} catch (FileNotFoundException | ClassNotFoundException e) {
System.out.println(e);
}
}
- 나열된 예외 클래스들이 부모-자식 관계에 있을 경우 오류가 발생한다. (중복으로 판단)
다중 예외처리 시 주의사항
- 예외가 다양한 경우 가장 최상위 클래스인 Exception 클래스에서 예외를 처리할 수 있다.
- 단 Exception 클래스는 모든 예외 클래스의 최상위 클래스이므로 가장 마지막 블록에 위치해야 한다.
ThrowException ex = new ThrowException();
try {
ex.loadClass("b.txt", "java.lang.string");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
try-catch-finally 문
- finally에서 프로그램 리소스를 정리함
- try{} 블럭이 실행되면 finally{} 블록은 항상 실행됨
- 리소스를 정의하는 코드를 각 블록에서 처리하지 않고 finally에서 처리함
public class ExceptionTest {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("a.txt");
} catch (FileNotFoundException e) {
System.out.println(e);
} finally {
try {
fis.close();
} catch (IOException e) {
System.out.println(e);
} finally {
System.out.println("finally");
}
}
}
}
try-catch-resouces 문
- 리소스를 자동 해제하도록 제공해주는 구문
- 자바 7부터 제공
- close()를 명시적으로 호출하지 않아도 try{} 블록에서 열린 리소스는 정상적인 경우 / 예외 발생한 경우 모두 해제됨
- 해당 리소스가 AutoCloseable을 구현해야 한다.
- FileInputStream의 경우 AutoCloseable을 구현하고 있다.
AutoCloseable의 구현 및 사용
package exceptionex;
public class AutoCloseableObject implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("close");
}
}
package exceptionex;
import org.junit.jupiter.api.Test;
public class exceptionexTest {
@Test
void autoCloseableTest() {
try (AutoCloseable obj = new AutoCloseableObject()){
throw new Exception();
} catch (Exception e) {
System.out.println(e);
}
}
}
//close
//java.lang.Exception
FileInputStream의 AutoCloseable 사용
package exceptionex;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class ThrowException {
public Class loadClass(String fileName, String className) throws FileNotFoundException, ClassNotFoundException {
FileInputStream fis = new FileInputStream(fileName);
Class aClass = Class.forName(className);
return aClass;
}
public static void main(String[] args) {
ThrowException ex = new ThrowException();
try {
ex.loadClass("b.txt", "java.lang.string");
} catch (Exception e) {
System.out.println(e);
}
}
}
향상된 try-with-resource 문
- 자바 9에서 제공되는 구문
- 외부에 선언된 리소스도 변수만으로 사용 가능
//자바 9 이전
AutoCloseableObject obj = new AutoCloseableObject();
try(AutoCloseableObject obj2 = obj) {
throw new Exception();
} catch (Exception e) {
System.out.println("Exception");
}
//자바 9 이후
AutoCloseableObject obj = new AutoCloseableObject();
try(obj) {
throw new Exception();
} catch (Exception e) {
System.out.println("Exception");
}
throw - 예외 발생하기
- throw 키워드를 이용하여 고의로 예외를 발생
public static void main(String[] args){
try{
// .. do something
}catch(Exception e){
throw new IllegalStateException("...");
}finally{
System.out.println("시스템 종료");
}
}
throws - 예외 미루기
- 메서드 선언부에 throws를 추가
- 예외가 발생한 메서드에서 예외 처리를 하지 않고 이 메서드를 호출한 곳에서 예외 처리
- main() 에서 throws를 사용하면 가상머신에서 처리된다.
public class Test{
static void callDriver() throws ClassNotFoundException{
Class.forName("oracle.jdbc.driver.OracleDriver");
System.out.println("완료");
}
public static void main(String[] args){
try{
callDriver();
}catch(ClassNotFoundException e){
System.out.println("클래스를 찾을 수 없습니다.");
}finally{
System.out.println("시스템 종료");
}
}
}
커스텀한 예외 만드는 방법
- checked Exception을 구현할 경우 Exception 확장
- Unchecked Exception을 구현할 경우 RuntimeException 확장
4가지 Best Practices를 따르는 것이 좋다.
- Java 표준 예외를 사용하는 것 보다 작성한 Custom 예외를 사용하는게 더 많은 이익을 얻는다고 생각할 경우에만 구현하자
- 작성한 Custom Exception 클래스 이름의 끝은 "Exception"으로 끝나도록 하자.
- API 메소드가 어떤 하나의 예외를 기술하고 있다면, 그 예외는 API의 한 부분이 되는 것이며 그 예외를 문서화 해야만 한다.
- 예외의 Cause를 설정할 수 있는 생성자를 제공하여야 한다.
public class OutOfStuNumException extends Exception{
public OutOfStuNumException(){} // 기본 생성자
public OutOfStuNumException(String message){
super(message); // 에러메세지 생성자
}
}
public void addStuNum(Student student) throws OutOfStuNumException{
if(studentNum > 20){
throw new OutOfStuNumException("학생번호가 20을 초과할 수 없습니다.");
}else{
studentNum++; // 학생 번호 증가
}
}
Exception in thread "main" exceptionex.OutOfStuNumException: 학생번호가 20을 초과할 수 없습니다.
at exceptionex.Student.addStuNum(OutOfStuNumException.java:12)
at exceptionex.OutOfStuNumException.main(OutOfStuNumException.java:29)
자바가 제공하는 기본 예외들
Arithmetic Exception
- 산술 연산에서 예외 조건이 발생했을 때
- 대표적인 예로는 / by Zero
ArrayIndexOutOfBounds Exception
- 잘못된 인덱스로 Array를 액세스 했을 경우 발생
- 인텍스가 음수이거나 배열 크기보다 크거나 같을 때 발생
ClassNotFoundException
- 정의한 클래스를 찾을 수 없을 때 발생하는 예외
FileNotFoundException
- 파일에 액세스 할 수 없거나 열리지 않을 경우 발생
IOException
- 입출력 작업이 실패하거나 중단될 때 발생
InterruptedException
- thread가 waiting, sleeping 또는 어떤 처리를 하고 있을 때 interrupt가 되면 발생
NoSuchMethodException
- 찾을 수 없는 메서드에 액세스 할 때 발생
NullPointerException
- Null 객체의 멤버를 참조할 때 발생
NumberFormatException
- 메서드가 문자열을 숫자 형식으로 변환할 수 없는 경우 발생
StringIndexOutBoundsException
- 문자열에 액세스 하는 인덱스가 문자열보다 큰 경우나 음수일 때 발생
'Back-end > java' 카테고리의 다른 글
스터디 11주차 - Enum (0) | 2021.07.05 |
---|---|
스터디 10주차 - 멀티쓰레드 프로그래밍 (0) | 2021.07.02 |
스터디 8주차 - 인터페이스 (0) | 2021.07.01 |
스터디 7주차 - 패키지 (0) | 2021.07.01 |
스터디 6주차 - 상속 (0) | 2021.06.30 |