TIL_230227_자바의 정석 복습_예외 처리

창고·2023년 2월 27일
0

본 내용은 <자바의 정석> 내용을 복습, 정리하였습니다.

Chapter 8. 예외 처리

1. 예외 처리(exception handling)

(1) 프로그램 오류와 예외 클래스

  • 프로그램 에러 또는 오류 : 프로그램이 실행 중 오작동을 하거나 비정상적으로 종료되는 경우, 이러한 결과를 초래하는 원인
  • 프로그램 오류의 종류
    • 컴파일 에러 : 컴파일 시에 발생하는 에러
    • 런타임 에러 : 실행 시에 발생하는 에러
    • 논리적 에러 : 실행은 되지만 의도와 다르게 동작하는 것
  • 소스 코드를 컴파일 할 경우 컴파일러가 소스 코드(.java)에 대해 오타, 잘못된 구문, 자료형 체크 등의 기본적 검사를 수행하여 컴파일 에러를 잡아냄. 다만 런타임 오류 등의 실행 도중 발생할 수 있는 잠재적 오류까지는 검사할 수 없음
  • 런타임 시 발생할 수 있는 에러와 예외의 구분
    • 에러(error) : 프로그램 코드에 의해서 수습될 수 없는 심각한 오류
      • StackOverflowError, OutOfMemoryError
    • 예외(exception) : 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류
  • 예외 클래스의 계층 구조
    • java에서는 실행 시 발생할 수 있는 오류(Exception, Error)에 대해 클래스로 정의하였으며 Object 클래스의 자손임
    • 모든 예외의 조상 클래스는 Exception 클래스, 모든 에러의 조상 클래스는 Error 클래스
    • 예외 클래스들은 두 그룹으로 나눌 수 있음
      • Exception 클래스와 그 자손들 (RuntimeException 계열 제외) : 사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외
      • RuntimeException 클래스와 그 자손들 : 프로그래머의 실수로 발생하는 예외

(2) 예외 처리하기 - try-catch

  • 예외 처리의 정의와 목적
    • 정의 : 프로그램 실행 시 발생할 수 있는 예외에 대비한 코드를 작성
    • 목적 : 프로그램의 비정상 종료를 막고 정상적인 실행 상태를 유지
    • 발생된 예외를 처리하지 못하면 프로그램은 비정상 종료되며 처리되지 못한 예외는 JVM의 예외 처리기(UncaughtExceptionHandler) 가 받아 예외의 원인을 화면에 출력
  • try-catch문 : 예외를 처리하기 위해서 사용
try {

	// 예외가 발생할 가능성이 있는 문장
    // try 블럭 내에서 예외 발생 시 발생한 예외와 일치하는 catch 블럭이 있는지 확인
    // 일치하는 catch 블럭이 없다면 예외는 처리되지 못함
    
} catch (발생할 예외 e) {

	// 예외 발생 시 처리할 문장
    
}

// try 블럭 내에서 예외가 발생하지 않는다면 try-catch문을 빠져나가서 수행을 계속
  • printStackTrace() : 예외 발생 당시의 호출 스택(call stack)에 있었던 메서드의 정보와 예외 메시지를 화면에 출력
  • getMessage() : 발생한 예외 클래스의 인스턴스에 저장된 메시지를 얻음
  • 멀티 catch 블럭 : JDK 1.7부터 지원, | 기호를 사용하여 여러 개의 catch 블럭을 하나로 합칠 수 있음
try {

} catch (ExceptionA | ExceptionB | ExceptionC e) {

}

(3) 예외 처리하기 - 메서드에 예외 선언

  • 예외를 메서드에서 선언하는 방법으로도 예외를 처리할 수 있음
  • 메서드 선언부에 키워드 throws를 이용, 발생할 수 있는 예외를 명시
public void example() throws IOException, DataAccessException {

}
  • 정확하게는 예외를 처리한다기보다는 자신(예외가 발생할 수 있는 메서드)을 호출한 메서드에게 예외를 전달하여 예외 처리를 떠맡기는 것 -> 어느 한 곳에서는 반드시 예외 처리를 해줘야 함
  • try-catch문과 메서드 예외 선언의 활용 방안
    • 예외가 발생한 메서드 내에서 자체적으로 처리해도 되는 것은 메서드 내에서 try-catch문 사용
    • 메서드 내에서 자체적으로 해결이 안되는 경우에는 예외를 메서드에 선언하여 호출한 메서드에서 처리해야 함

(4) finally

  • finally 블럭 : 예외의 발생 여부에 상관 없이 실행되어야 할 코드를 포함시킬 목적으로 사용
try {

} catch (Exception e) {

} finally {
	// 예외 발생 여부와 관계 없이 항상 수행되어야 하는 문장들
    // try-catch문의 마지막에 위치
}

(5) 자동 자원 반환 - try-with-resource문

  • JDK 1.7부터 try-catch문의 변형으로 새로 추가됨. 입출력 관련 클래스 사용 시 유용
  • 입출력 수행 시 항상 finally 블럭에 자원을 반환하도록 close() 처리를 해야 하는데 이 때 IOException이 발생할 수 있어 추가로 try-catch문을 사용해야 했음
  • try-with-resource문의 경우 try문의 괄호 안에 객체 생성 문장을 넣을 경우 따로 close()를 호출하지 않아도 try 블럭을 벗어나는 순간 자동적으로 close()가 호출되며 다음 catch 블럭 또는 finally 블럭에 수행됨
// 기존
try {
	fis = new FileInputStream("score.dat");
    dis = new DataInputStream(fis);
} catch (IOException e) {
	e.printStackTrace();
} finally {
	try {
    	if(dis!=null) dis.close();
    } catch (IOException e) {
    	e.printStackTrace();
    }
}    

// try-with-resource
try (fis = new FileInputStream("score.dat");
	dis = new DataInputStream(fis);){

...

} catch (IOException e) {
	e.printStackTrace();
} 
  • 억제된 예외 : 예외가 동시에 2개 이상 발생할 경우 실제 발생한 예외가 아닌 다른 예외를 억제된 예외(suppressed exception) 으로 다루며 Throwable에 억제된 예외와 같은 메서드가 정의됨
void addSuppressed(Throwable exception) // 억제된 예외를 추가
Throwable[] getSuppressed() // 억제된 예외(배열)을 반환

(6) 사용자 정의 예외

  • 사용자 정의 예외 : 프로그래머가 필요에 의해 새로운 예외 클래스를 정의한 것, 다른 예외 클래스를 상속받아서 만듬
public class MyException extends RuntimeException {

	public MyException() {
    	super();
    }

}
  • 프로그래밍 환경이 바뀌어 현재로서는 필수적으로 처리해야 할 것 같았던 예외들이 선택적으로 처리해도 되는 상황으로 바뀌고 있는 추세
    • 필요에 따라 예외 처리의 여부를 선택할 수 있는 'unchecked 예외' 가 강제적인 'checked 예외' 보다 더 환영받고 있음

(7) 예외 되던지기(exception re-throwing)

  • 예외를 처리한 후 인위적으로 다시 예외를 발생시키는 방법
  • try-catch 블록을 통해 발생 가능성이 있는 예외를 처리해주고 catch 블록에서 다시 throw문을 활용해 예외를 다시 발생 시킴
try {
	
} catch (Exception e) {
	throw new NewException();
}

(8) 연결된 예외(chained exception)

  • 한 예외가 다른 예외를 발생시킬 수 있음
Throwable initCause (Throwable cause) // 지정한 예외를 원인 예외로 등록
Throwable getCause() // 원인 예외를 반환
  • 원인 예외를 등록해 다시 예외를 발생시키는 이유
    • 여러 가지 예외를 하나의 큰 분류의 예외로 묶어서 다루기 위함
    • checked 예외를 unchecked 예외로 바꾸기 위함
// 감싸기 전
public void test throws SpaceException, MemoryException {

	if (!enoughSpace()) throw new SpaceException();
    
    // Exception의 자손이므로 checked 예외라 반드시 예외 처리를 해야 함
    if (!enoughMemory()) throw new MemoryException(); 

}

// 감싼 후
public void test throws SpaceException {

	if (!enoughSpace()) throw new SpaceException();
    
    // RuntimeException으로 감싸 unchecked 예외가 됨
    if (!enoughMemory()) throw new RuntimeException(new MemoryException); 

}
profile
공부했던 내용들을 모아둔 창고입니다.

0개의 댓글