🏃♂️ 들어가기 앞서..
본 게시물은 스터디 활동 중에 작성한 게시물로 자바의 정석-기초편 교재를 학습하여 정리하는 글입니다.
※ 스터디 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
내 처리문은 실행됨. )