[Java] 예외처리 : try-catch, finally

정재현·2024년 1월 3일

Java

목록 보기
32/43
post-thumbnail

오류 및 예외에 대한 이해

오류(Error) vs 예외(Exception)

오류(Error)란?

  • 일반적으로 회복이 불가능한 문제
  • 시스템 레벨에서, 또는 주로 환경적인 이유로 발생
  • 코드의 문제로 발생하는 경우도 있지만, 일단 발생하는 경우 일반적으로 회복이 불가능
  • 에러가 발생한 경우 우리는 어떠한 에러로 프로그램이 종료되었는지를 확인하고 대응해야 함

예외(Exception)란?

  • 일반적으로 회복이 가능한 문제
  • 회복이 가능하다는 전제는 우리가 “그 예외가 발생할 수 있다는 것을 인지하고, 대응했을 것
  • 현실적으로 코드레벨에서 할 수 있는 문제상황에 대한 대응은 “예외처리”에 속함.

예외 클래스 구조 : 자바의 Throwable Class

  • 모든 객체의 원형인 Object 클래스에서 시작
  • Object클래스 밑에는 문제 상황을 뜻하는 Throwable클래스가 Object클래스를 상속
    • Throwable클래스는 모든 문제 상황을 다 포함하는 클래스
  • Throwable 클래스의 자식으로 에러(Error)예외(Exception) 클래스가 존재
  • 에러(Error) 클래스와 예외(Exception) 클래스는 각각 IOError 클래스, RuntimeException 클래스와 같이 구분하여 처리된다.


예외의 종류

컴파일 에러(예외)

  • .java 파일.class 파일로 컴파일할때 발생하는 에러
  • 대부분 자바 프로그래밍 언어의 규칙을 지키지 않았기 때문에 발생
    ex. 있지 않은 클래스를 호출한다거나, 접근이 불가능한 프로퍼티나 메소드에 접근한다거나 하는 경우에 발생
  • 해결방법
    • 문법에 맞게 다시 작성

런타임 에러(예외)

  • 문법적인 오류는 아니라서, 컴파일은 잘 되었지만 “프로그램”이 실행도중 맞닥뜨리게 되는 예외

예외 처리 관점에서 예외의 종류

  • 확인된 예외(Checked Exception)
    • 예외가 발생하는 상황을 인지하고, 어떠한 에러인지 미리 정의를 해놨기 때문에 컴파일 에러와 다름
    • 컴파일 하는동안 이 예외에 대한 예외처리를 했는지 확인할 수 있는 예외
  • 미확인된 예외(Unchecked Exception)
    • 런타임 시점에 확인되는 예외
    • 예외 처리가 반드시 필요하지 않은 예외
    • 컴파일 하는동안 이 예외에 대한 예외처리를 했는지 확인할 수 없는 예외

예외 처리하기

1. 예외 정의하기

  • 예외 클래스를 만들어 발생할 수 있는 예외를 미리 정의
  • OurBadException : 발생이 예상되는 예외 사항
	class OurBadException extends Exception {
		public OurBadException() {
			super("위험한 행동을 하면 예외처리를 꼭 해야합니다!");
		}
	}

2. 예외가 발생할 수 있음 알리기 : Throw, Throws

throws

  • 메서드 이름 뒤에 위치
  • 메서드가 어떠한 예외사항을 던질 수 있는지 알려주는 예약어
  • 여러 종류의 예외사항을 적을 수 있다.

throw

  • 메서드 안에 위치
  • 실제로 예외 객체를 던질 때 사용하는 예약어
  • 실제로 던지는 예외 객체 하나와 같이 사용
  • return 키워드처럼 throw아래의 구문들은 실행되지 않고 메서드가 종료됨.

예시

// OurClass.java

	class OurClass {
	    private final Boolean just = true;
		
	    public void thisMethodIsDangerous() throws OurBadException {	// throws : 예외 확인
	        if (just) {
	            throw new OurBadException();	// throw : 새로운 예외 객체를 만들어서 던짐
	        }
	    }
	}

3. 예상되는 예외 다루기 : try - catch - finally

  • 이미 OurClass.java에서 throw를 통해서 thisMethodIsDangerous()가 예외를 발생시킬 수 있다고 정의했기 때문에 try-catch-finally 구분을 사용해야 한다
// StudyException.java

// 일단 try해
// ~~~그리고 예외가 발생하면 그걸 잡아(catch)
// 그리고, 정식적으로 수행되든, 예외가 발생하든 결국, 마침내 수행돼야 하는 로직을 'finally' 수행해!

	public class StudyException {
	    public static void main(String[] args) {
	        OurClass ourClass = new OurClass();

	        try {
	            // 1. 위험한 메소드의 실행을 "시도" 해 봅니다.
	            // "시도" 해보는 코드가 들어가는 블럭입니다.
	            ourClass.thisMethodIsDangerous();
	        } catch (OurBadException e) {
	            // 2. 예외가 발생하면, "잡아서" handling 합니다.
	            // 예외가 발생하는경우 "handling" 하는 코드가 들어가는 블럭입니다.
				// 즉 try 블럭 내의 구문을 실행하다가 예외가 발생하면
				// 예외가 발생한 줄에서 바로 코드 실행을 멈추고
				// 여기 있는 catch 블럭 내의 코드가 실행됩니다.
	            System.out.println(e.getMessage());
	        } finally {
	            // 3. 예외의 발생 여부와 상관없이, 실행시켜야 하는 코드가 들어갑니다.
	            // 무조건 실행되는 코드가 들어가는 블럭입니다.
	            System.out.println("우리는 방금 예외를 handling 했습니다!");
	        }
	    }
	}

연결된 예외(Chained Exception)란

  • 예외의 원인이 연결되어 있어 한 예외가 다른 예외를 유발할 수 있는 경우를 말함
    • A의 예외 원인은 B에 있고, B의 예외 원인이 C에 있는 경우 연결된 예외 상황이라고 볼 수 있다.
  • 예외 A가 예외 B를 발생시켰다면, 예외 A는 B의 원인 예외가 된다.

정의

  • 원인 예외가 새로운 예외를 발생시키는 경우를 예외 연결이라 한다.

원인 예외를 다루기 위한 메소드

  • initCause() : 지정한 예외를 원인 예외로 등록하는 메소드
  • getCause() : 원인 예외를 반환하는 메소드

예외 처리하기

방법 1. 예외 복구

  • 실제로 try-catch로 예외를 처리하고 프로그램을 정상 상태로 복구하는 방법
    • 만약 오류가 생긴다면, 오류사항으로 인해 프로그램을 종료하는 대신 default값을 반환하는 형식으로 정상상태로 복구 시도
  • 가장 기본적인 방식이지만, 현실적으로 복구가 가능한 상황이 아닌 경우가 많거나 최소한의 대응만 가능한 경우가 많기 때문에 자주 사용하는 방법은 아님
	public String getDataFromAnotherServer(String dataPath) {
		try {
			return anotherServerClient.getData(dataPath).toString();
		} catch (GetDataException e) {
				return defaultData;
		}
	}

방법 2. 예외 처리 회피

  • ex. someMethod()에서 발생한 에러가 someIrresponsibleMethod()throws를 통해서 그대로 다시 흘러나가게하여 예외 처리 회피.
    • 물론 같은 객체내에서 이런일은 하지는 않음, 예외처리 회피를 보이기 위한 단순한 예시 코드
  • 관심사를 분리해서 한 레이어에서 처리하기 위해서 이렇게 에러를 회피해서 그대로 흘러 보내는 경우도 있다.
	public void someMethod() throws Exception { ... }

	public void someIrresponsibleMethod() throws Exception {
		this.someMethod();
	}

방법 3. 예외 전환

  • 예외처리 회피하기의 방법과 비슷하지만, 조금더 적절한 예외로 다시 던져주는 경우
  • 보통은 예외처리에 더 신경쓰고싶은 경우나, 오히려 RuntimeException처럼 일괄적으로 처리하기 편한 예외로 바꿔서 던지고 싶은 경우 사용
	public void someMethod() throws IOException { ... }

	public void someResponsibleMethod() throws MoreSpecificException {
		try {
			this.someMethod();
		} catch (IOException e) {
			throw new MoreSpecificException(e.getMessage());
		}
	}

profile
공부 기록 보관소

0개의 댓글