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

  • 자바에서 예외 처리 방법 (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를 따르는 것이 좋다.

  1. Java 표준 예외를 사용하는 것 보다 작성한 Custom 예외를 사용하는게 더 많은 이익을 얻는다고 생각할 경우에만 구현하자
  2. 작성한 Custom Exception 클래스 이름의 끝은 "Exception"으로 끝나도록 하자.
  3. API 메소드가 어떤 하나의 예외를 기술하고 있다면, 그 예외는 API의 한 부분이 되는 것이며 그 예외를 문서화 해야만 한다.
  4. 예외의 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

+ Recent posts