JAVA 8. 예외처리

김창민·2024년 7월 25일

BE

목록 보기
10/50

문제 발생

코드를 작성하다 보면 많은 문제를 직면하게 된다. ;를 빼먹어서 발생하는 오류부터 컴퓨터 하드웨어 문제까지 발생하게 되는데 오류를 해결할 수 있으면 해결하는거 부터 회피 까지 개발자의 역량에 따라 문제에 대응할 수 있게 된다.

오류

오류(Error)는 일반적으로 회복이 불가능한 문제다. 시스템 레벨 혹은 환경적 문제로 발생하게 되며 일단 발생하면 사실 회복이 불가능하다.

이럴땐 어떤 에러로 프로그램이 종료되었는지 확인하고 사후 대응을 해야한다.

예외

예외(Exception)는 일반적으로 회복이 가능한 문제다. 회복이 가능한 것에는 조건이 있는데, 해당 Exception이 발생할 수 있음을 인지하고 대응책을 마련했을 경우 회복이 가능하다.

대응책을 우리는 예외 처리라고 한다.


예외 종류

총 2개의 관점으로 예외를 볼 수 있다. 코드 실행 관점과 예외 처리 관점이다. 먼저 코드 실행 관점에서 가장 많이 마주치는 예외는 크게 컴파일 에러와 런타임 에러로 구분된다.

코드 실행 관점

컴파일 에러

컴파일. 즉 .java -> .class로 변환시에 발생하는 에러.

대부분 자바언어의 규칙을 지키기 않을 때 발생한다.
이 경우 그냥 문법에 맞춰 수정하면 된다.

런타임 에러

문법적 오류는 아니라서 컴파일은 되지만, 프로그램이 실행 도중 만나는 예외다.

예를 들어서 어떤 값을 0으로 나눈다던가..

예외처리 관점

예외처리 관점에선 확인된 예외(Checked Exception), 미확인된 예외(Unchecked Exception)로 구분할 수 있다.

확인된 예외

컴파일 시점에 확인하는 예외로 반드시 예외 처리를 해야한다. (컴파일 에러 아님)

미확인된 예외

런타임 시점에 확인되는 예외다. 예외처리가 필요할 수도 있는 예외이다.


예외 정의하기

일단 기본적으로 자바에선 예외를 표현한 Exception 클래스가 존재한다. 하지만 나만의 예외를 정의하고 싶다면 다음과 같이 하면 된다.

class MyException extends Exception {
	public MyException() {
		super("멈춰!");
	}
}

자바의 내장 예외 클래스 Exception을 상속받는 나만의 예외 클래스를 만들면 된다.


throw, throws

throws : 메서드 이름 뒤에 붙여서 이 메서드가 어떤 예외 사항을 던질 수 있는지 알리는 예약어
throw : 메서드 안에서 예외 객체를 던지는 예약어. return처럼 작동하면 해당 메서드는 끝난다.

class OurClass {
    private final Boolean just = true;
		
		
    public void thisMethodIsDangerous() throws OurBadException {
        if (just) {
            throw new OurBadException();
        }
    }
}

예외 핸들링

자바에서 예외 핸들링은 try-catch, finally다.

try{
	//예외가 발생할거 같은 부분
}catch(예외클래스 변수명){
	//catch 매개변수의 예외 발생시 실행문
    //모든 예외를 대상으로 하고싶으면 Exception하면 된다.
}finally{
	//예외가 발생해도 이 부분은 실행한다.
}

으로 사용하면 된다.
한번에 모든 예외를 처리하는 Exception말고 예외클래스당 다른 catch문을 적용하고싶으면 catch문을 더 많이 만들어도 된다. 1개의 try에 50개의 catch..도 가능하다


Chained Exception

예외는 다른 예외를 유발하기 마련이다. A예외로 인해서 B예외가 발생했다면 A는 B의 원인 예외라고 한다.

원인 예외를 새로운 예외에 등록한 후 다시 새로운 예외를 발생시키면 예외 연결이라고 한다.

예외를 연결하는 이유는 여러 종류의 예외를 하나로 묶어서 처리하기 위함이다.

initCause()

지정한 예외를 원인 예외로 등록하는 메소드

getCause()

원인 예외를 반환하는 메소드

public class main {

    public static void main(String[] args) {
        try {
            // 예외 생성
            NumberFormatException ex = new NumberFormatException("가짜 예외이유");

            // 원인 예외 설정(지정한 예외를 원인 예외로 등록)
            ex.initCause(new NullPointerException("진짜 예외이유"));

            // 예외를 직접 던집니다.
            throw ex;
        } catch (NumberFormatException ex) {
            // 예외 로그 출력
            ex.printStackTrace();
            // 예외 원인 조회 후 출력
            ex.getCause().printStackTrace();
        }

        // checked exception 을 감싸서 unchecked exception 안에 넣습니다.
        throw new RuntimeException(new Exception("이것이 진짜 예외 이유 입니다."));
    }
}

이러면 Caused by: java.lang.NullPointerException: 진짜 예외이유 이렇게 출력된다.


실질적 예외 처리

예외 복구

try-catch로 예외를 처리하고, 프로그램을 정상 상태로 복구하는 방법이다.

가장 기본적인 방식이지만, 현실적으로 복구가 힘들거나 최소한의 대응만 경우가 많아 자주 사용하지 않는다.

public String getDataFromAnotherServer(String dataPath) {
		try {
				return anotherServerClient.getData(dataPath).toString();
		} catch (GetDataException e) {
				return defaultData;
		}
}

예외 처리 회피

public void someMethod() throws Exception { ... }

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

이런 느낌으로 예외 처리를 회피할 수 있다. 다만, 위 코드는 동일 객체에서 발생한 예외를 동일 객체에서 회피하지만 실제로는 이렇게 안한다.

예외 전환

처리 회피와 비슷하지만 적절한 예외를 던지는 방법이다.

public void someMethod() throws IOException { ... }

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

더 디테일한 예외 처리를 하고싶거나, RuntimeException처럼 일괄적으로 처리하기 편한 예외로 바꾸기 위해 사용한다.

profile
일일 회고 : https://rlackdals981010.github.io/

0개의 댓글