[JAVA] 예외 처리 (2)

DongGyu Jung·2022년 2월 5일
0

자바(JAVA)

목록 보기
21/60
post-thumbnail

🏃‍♂️ 들어가기 앞서..

본 게시물은 스터디 활동 중에 작성한 게시물로 자바의 정석-기초편 교재를 학습하여 정리하는 글입니다.
※ 스터디 Page : 〔투 비 마스터 : 자바〕

*해당 교재의 목차 순서와 구성을 참고하여 작성하며
각 내용마다 부족할 수 있는 내용이나 개인적으로 궁금한 점은
추가적인 검색을 통해 채워나갈 예정입니다.



🧨 고의적 예외

키워드 throw를 사용해서 고의로 예외를 발생시킬 수 있다.

1. 연산자 new를 이용하여 예외 클래스 객체생성한다.
2. 키워드 throw를 이용해 예외발생시킨다.

Exception(예외) 인스턴스를 생성할 때,

"생성자에 String(문자열) "을 넣어주면
해당 문자열은 인스턴스에 메세지로 저장된다.
( getMessage()를 이용해 출력할 수 있다. )

public static void main(String args[]) {
    try {
        Exception e = new Exception("고의적 예외 발생") ; // 예외 클래스 인스턴스 생성
        throw e ; // 예외 발생
        // throw new Exception("고의적 예외 발생") ;  이렇게 한줄로도 작성 가능
    } catch (Exception e) {
        System.out.println("에러 메세지 : " + e.getMessage() ) ; // "에러 메세지 : 고의적 예외 발생" 출력
        e.printStackTrace() ; // 해당 예외 정보 출력
    }
    System.out.println("정상 종료") ; // try-catch문이 정상적으로 처리되어 종료되고 이후 실행문 정상 처리됨.
}

checked 예외 / unchecked 예외

  • checked 예외 : 컴파일러가 " 예외 처리 여부 "를 체크Exception클래스 & 그 자손
    ( 예외 처리 필수 )

  • unchecked 예외 : 컴파일러가 " 예외 처리 여부 "를 체크하지 않음RuntimeException클래스 & 그 자손
    ( 예외 처리 선택 )


    ※ 이전 글 참고 ( 예외처리(1) )

<checked 예외>,
즉, Exception 클래스와 그 자손클래스 인스턴스를 생성하고 throw하게되면
오류가 발생한다.
try-catch문을 통해 예외 처리를 해주어야 한다.

그에 반해
<unchecked 예외>,
즉, RuntimeException 클래스와 그 자손클래스 인스턴스를 생성하고
예외처리문 없이 예외를 발생시키더라도
컴파일이 문제없이 완료된다.
( 이 unchecked 예외는 프로그래머 실수로 발생하는 것들이기 때문에 강제되지 않는 것이다. )


💨 "메서드" ← 예외 선언

지금까지 예외처리문을 작성할 때,
" try-catch문 "을 사용하였다.

이번엔
새로운 예외처리 방법을 알아볼 것이다.
바로
" 예외 선언 "을 하는 것과
" 은폐 "하는 것이다.
(이 " 은폐 "는 try catch문에서 catch문에 아무 처리문 작성을 하지 않아 숨기는 것이다. 권장X )


간단히 말하자면
try-catch문 은
" 프로그래머가 직접 예외를 처리하는 것 "이고

예외 선언
메서드를 통해
" 발생한 예외를 호출한 쪽에 알리는 것 "이다.
( 단, 키워드는 throw가 아닌 throws임을 주의 )

/*
키워드는 " throws "를 사용하며
예외가 여러 개일 경우, 쉼표(,)를 통해 구분
*/
void method() throws Exception1, Exception2, ..., ExceptionN {
    // 메서드 작성
}

// method() 에서 Exception & 그 자손 예외 발생 가능
void method() throws Exception { // 모든 종류의 예외가 발생 가능 
	// ▶ 겉보기엔 하나이지만 실제로는 여러 예외 종합
    // 메서드 작성
}

(참고 : 오버로딩vs오버라이딩)
"오버라이딩"의 조건 중 하나가
" 조상보다 많은 예외 선언 X "인 것 기억날 것이다.
그래서 아래와 같이
자손이 더 넓은 범위를 오버라이딩 하게되면
문법적 오류가 발생하게 된다.

/* 가능 */
class child extends parent {
	// 자손이 범위를 줄여서 오버라이딩
    void method() throws RuntimeException{}
}
class parent {
    void method() throws Exception{}
}

/* 불가능 _ 문법적 에러 */
class child extends parent {
	// 자손이 더 넓은 범위를 오버라이딩 -> 에러
    void method() throws Exception{}
}
class parent {
    void method() throws RuntimeException{}
}

보통 예외 선언은
직접 해결할 수 없는 문제를 알릴 때 유용하다.
예를 들어,
메모리저장공간이 부족할 경우에 사용할 수 있다.

// 메모리& 저장공간 사유 발생 가능성있는 예외 선언 메서드
static void Install() throws SpaceException, MemoryException {
    if(!enoughSpace())
        throw new SpaceException("설치 공간 부족") ;
    if(!enoughMemory())
        throw new MemoryException("메모리 부족");
}

※ 자바 API를 사용할 때 공식문서를 살펴보면 발생 가능한 예외에 대한 정보도 공시되어있으니 참고하면 좋음
(「 Oracle Docs : JDK API 」)

" 전달 "이라는 과정
즉, " 알리는 것 "이 어떻게 진행되는지 이해하는 것이 좋다.

처리되는 것이 아닌
단순 넘겨주는 것이기 때문에
아래와 같이 결과적으로 비정상적인 종료가 발생한다.
( 단, 선언되었기 때문에 컴파일 에러가 발생하는 것은 아님 !! )

/* 
비정상적으로 종료된 코드 
( Exception 예외이기 때문에 처리 필수 )
*/
// main에서도 예외처리가 없기 때문에 비정상적인 종료
public static void main(String[] args) throws Exception {
	//method1에서도 예외처리가 없다.
    method1() ; // 예외 전달받음
}
static void method1() throws Exception {
	// method2에서 예외처리가 없기 때문에
    method2() ; // method2에서 생성한 예외 전달받음
}
static void method2() throws Exception {
    throw new Exception() ; // 예외 생성
    // 예외처리 없음
}

교재에 있는 예제를 참고해보자면

import java.io.* ;
...
public static void main(String[] args) {
    try {
        File f = createFile(args[0]);
        System.out.println(f.getName() + "파일이 성공적으로 저장") ;
    } catch (Exception e) {
        // createFile 메서드에서 반환(넘겨받은)된 것이
        // " 예외 "일 경우 catch로 처리됨.
        System.out.println(e.getMessage() + "다시 입력 바람.") ;
    }
}

static File createFile(String fileName) throws Exception {
    if (fileName == null || fileName.equals(""))
        //인수로 받은 fileName 문자열이 빈 문자열일 때
        throw new Exception("파일이름 유효하지 않음."); // 인스턴스에 메세지 저장
    
    //정상처리의 경우
    File f = new File(fileName);
    f.createNewFile();
    // 만약 여기서 예외 처리를 하면 main메서드에서는 발생했는지 모름.
    return f
}

예외 발생 시,
발생한 해당 메서드에서 강제적으로 설정해서 반환하는 등
자체적으로 처리해도 되지만

다시 처리하는 작업이 필요한 경우
" 예외 선언 "을 활용해서
호출한 메서드에서 처리하도록 해야한다.


finally 블럭

이전에 R 언어 / 파이썬을 배울 때도 자주 본 것이지만

" 예외 발생여부 상관없이 무조건 실행되어야할 코드 "를 적는 공간이다.

try {
    //예외 발생 가능성있는 코드
} catch (Exception1 e1) {
    //예외 처리문
} finally {
    //예외발생 여부 상관없이 항상 수행되는 코드
    //무조건 try-catch 이후에 맨마지막에 위치해야함.
}

<예외가 발생했을 경우> 와
<예외가 발생하지 않은 경우>
어떤 경우든 실행할 필요가 있는 코드 를 작성하면 된다.
( try-catch내부에서 반환하는 return이 있더라도 finally 내 처리문은 실행됨. )

0개의 댓글