[자바 스터디] 9주차 과제: 예외 처리

yunu·2022년 7월 8일
0
post-thumbnail

9주차 과제: 예외 처리

목표

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

학습할 것

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

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

try { // 예외 발생 가능성이 있는 코드 블록
	...
    // try에서 예외가 발생하면 catch로 이동한다.
    // throw 키워드를 통해 직접 예외 인스턴스를 생성하는 경우
    if () {
    	throw new Exception("..."); - (1)
    }
    if () {
    	throw new ChildException("..."); - (2) // extends Exception
    }
   	if () {
    	throw new ChildChildException("..."); - (3) // extends ChildException
    }
    // 예외가 발생하면 try블록의 예외 아래 코드들은 실행되지 않고 무시된다. 그러므로 try블록의 return도 실행되지 않는다.
    ...
    return ...
// try블록에서 다양한 예외를 처리해주기 위해 그에 따라 여러 catch블록이 존재
// 그러므로 발생한 예외에 따라 어떤 catch블록가 처리해주는지 확인(catch블록의 Exception의 상속구조 확인)
} catch (ChildChildException e) { - (3)
	return ...;
} catch (ChildException e) { - (2)
	return ...;
} catch (Exception e) { - (1)
	return ...;
// java7 이후 catch블록에 하나 이상의 Exception(multi-catch) 사용가능, 사용하는 Exception들 상속관계 X
} catch (ExceptionA | ExceptionB e) {
	return ...;
} catch (ChildException | Exception e) { - 틀린 문법
	return ...;
} finally { // 예외 발생 여부와 관계없이 무조건 발생하는 블록
	// try와 catch가 실행된 후에도 작동, 즉 try와 catch에서 return이 호출되어도 finally는 호출된다.
    // 파일 입출력 이후 close을 해줄 때 많이 사용(resource leak를 방지하기 위한)
    // java7에서 try-with-resources로 파일 close를 finally블록 사용하지 않아도 자원 쉽게 해제 가능
}

try

  • 예외가 발생할 수 있는 코드를 넣는 곳
  • 코드의 로직에 의해 예외가 발생하는 경우와 직접 예외 인스턴스를 생성하는 경우가 있다.

catch

  • try블록에서 발생한 예외 코드나 예외 객체를 Argument로 전달받아 처리하는 곳
  • 예외가 발생하면 예외에 대해 어떤 식으로 처리할지 로직을 구현하는 곳

finally

  • try블록이 끝난 뒤 혹은 예상치 못한 에러가 발생했을 때도 실행을 보장, 코드의 흐름이 바뀌어도 항상 실행
  • JVM이 try catch를 실행하는 도중에 종료되거나 Thread가 try catch를 실행하는 도중에 interrupt 당하거나 kill 당한다면 finally블록은 실행되지 않는다.
  • 주로 cleanup code를 넣어서 resource leak를 막을 용도로 사용한다.
  • finally 블록 안에서 return 하는 경우 try 블록 안에서 발생한 예외는 무시되고 finally 블록을 거쳐 종료되어 어떤 예외가 발생했는지 알 수 없다. -> 안티 패턴이므로 finally 블론 안에서 return 하면 안된다.

try-with-resource (JAVA 7 이후)

  • try-with-resource로 모든 객체들을 close()가 호출해주는 것은 아니다.
  • AutoCloseable을 구현한 객체만 close()가 호출된다.(Closeable 인터페이스는 AutoCloseable을 상속받고 있다.)
  • AutoCloseable을 클래스에 implements 해주어 사용자가 직접 try-with-resource를 동작시키는 객체를 만들어 줄 수 있다.
  • 자원을 반납하는 과정에서 예외가 발생할 수도 있으므로 finally 블록 안에서 다시 한번 try/catch를 통해 예외처리를 해야 하지만 try-with-resource 을 사용하면 이 경우 동작 순서를 사용하여 예외처리를 해준다.
package java.lang;

public interface AutoCloseable {
    void close() throws Exception;
}
package java.io;

import java.io.IOException;

public interface Closeable extends AutoCloseable {
    public void close() throws IOException;
}
class Resource1 implements AutoCloseable {
	...
	@Override
    void close() throws Exception {
    	// finally블록에서 수행할 작업
    }
}

try (Resource1 r1 = new Resource1();
    Resource2 r2 = new Resource2()) {
	use(r1);
    use(r2);
} catch (Exception e) {
	...
}

try-with-resource의 동작 순서 - 확실하지 않음

try (Resource resource = new Resource()) {
	// - (1) : try블록
// - (2) : catch블록 시작 직전, (1)이 모두 진행된 이후 or (1)에서 예외 발생 이후 catch로 가지 전
} catch (Exception e) {
	// - (3) : catch블록
} finally {
	// - (4) : finally블록
}

(1) 예외가 없을 경우 정상적으로 try블록 동작 or 예외가 있을 경우 예외가 발생한 코드 이후는 무시
(2) (1)에서의 두가지 경우가 발생하면 try-with-resourceResourceclose()을 호출, 이때 close()함수에서도 예외를 발생시킬 수 있으므로 (3)번 이전에 실행되어 예외를 처리?
(3) try블록에서 발생한 예외 혹은 close()을 호출하면 발생한 예외처리, 하지만 catch는 하나의 예외만 처리할 수 있어 try블록의 예외 이후 close()의 예외도 발생하면 try블록의 예외가 먼저 예외처리되고 close()의 예외는 무시되는 것을 볼 수 있다.
(4) 모든 동작이 마무리되고 finally블록 동작

try-with-resource를 사용할 시 catch블록은 close()의 예외를 처리하는 용도로 사용하는 것 같다. 그렇기 때문에 try블록 안에는 새로운 예외가 발생하지 않도록 해야할 것 같다.

throw

  • 사용자 정의 예외를 생성한다.
  • 사용자가 강제적으로 예외를 발생시킬 수 있다. throw new Exception(param);
  • 생성한 예외를 catch 블록에서 받아줘야 한다.

throws

  • 예외를 처리하는 방식은 try-catch로 처리하든가 throws를 통해 Call Stack의 상위 메소드에게 예외처리를 위임한다. 실제로 예외를 처리하는 것은 try-catch이다.

try/finally

  • try와 catch를 같이 사용하지 않고 try와 finally만 사용하는 경우는 try의 예외 발생은 throws를 통해 상위 스택으로 위임하고 예외가 발생하거나 안하거나 finally블록을 통해 자원을 관리할 수 있도록 할 때 사용한다.
  • 하지만 이펙티브 자바 아이템 09. try-finally보다는 try-with-resouce를 사용하라

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


Exception과 Error의 차이는?

Error

  • 시스템에서 비정상적인 상황이 발생했을 경우에 발생한다. 메모리 부족 OutofMemoryError이나 스택오버플로우 StackOverflowError와 같이 복구할 수 없는 것을 말한다. 이러한 에러는 개발자가 예측하기도 쉽지 않고 처리할 수 있는 방법도 없다.

Exception

  • 프로그램 실행 중 개발자가 구현한 로직에서 예기치 않은 상황이 발생했을 경우이다. 배열의 범위를 벗어나거나 ArrayIndexOutOfBoundsException, 값이 null인 참조변수를 참조하는 경우 NullPointerException, 존재하지 않는 파일의 이름을 입력하는 경우 FileNotFoundException 등이 있다. 다음과 같은 예외는 충분히 예측하고 처리할 수 있다. 예외는 CheckedExceptionUncheckedException으로 나뉜다.

CheckedException

  • 반드시 예외를 처리해야 한다(복구가 가능한다). -> CheckedException 이 발생하는 부분에서 try/catch로 처리를 안해주면 컴파일 에러 발생, 또는 throws 로 던져야 한다.
  • 컴파일 시점에서 예외를 확인한다. -> 컴파일 시 예외 발생

UncheckedException

  • Error 와 RuntimeException 이 UncheckedException
  • 명시적으로 예외처리를 강제하지 않는다(복구가 힘들다). -> UncheckedException 이 발생하는 부분에서 try/catch로 처리를 강제하지 않아도 된다.
  • 실행 시점에서 예외를 확인한다. -> 컴파일 성공

RuntimeException과 RuntimeException가 아닌 것의 차이는?

RuntimeException

  • UncheckedException을 상속한 클래스
  • RuntimeException을 상속받은 예외들은 명시적인 예외처리를 강제하지 않는다.

Not RuntimeException

  • CheckedException을 상속한 클래스
  • RuntimeException이 아닌 예외들은 명시적으로 예외처리를 해야한다.

커스텀한 예외 만드는 방법

public class CustomException extends (Exception or RuntimeException) {
 
    // 1. 매개 변수가 없는 기본 생성자
    CustomException() {}

    // 2. 예외 발생 원인(예외 메시지)을 전달하기 위해 String 타입의 매개변수를 갖는 생성자
    CustomException(String message) {
        super(message); // RuntimeException 클래스의 생성자를 호출합니다.
    }
}

출처:
https://facingissuesonit.com/java-exception-handling/
https://codechacha.com/ko/java-try-with-resources/
https://ryan-han.com/post/java/try_with_resources/
https://velog.io/@youngerjesus/%EC%9E%90%EB%B0%94-%EC%98%88%EC%99%B8-%EC%B2%98%EB%A6%AC#the-finally-block
https://devlog-wjdrbs96.tistory.com/351
https://www.notion.so/3565a9689f714638af34125cbb8abbe8
https://veneas.tistory.com/entry/Java-%EC%BB%A4%EC%8A%A4%ED%85%80-%EC%98%88%EC%99%B8-%EB%A7%8C%EB%93%A4%EA%B8%B0Custom-Exception

profile
rip

0개의 댓글