JavaStudy Chap. 8

Java의 정석 챕터8 예외처리

- 예외처리

- 프로그램 오류

런타임에러를 두 가지로 구분
1. 에러 : 프로그램 코드에 의해 수습될 수 없는 심각한 오류
: 메모리부족, 스택오버플로우
2. 오류 : 프로그램 코드에 의해 수습 될 수 있는 약한 오류
: 프로그래머가 미리 이에 대비한 코드 작성


- 예외클래스의 계층구조

: 자바는 런타임에러를 클래스로 정의함 (역시나 최상위클래스는 Object)

  • 예외의 최상위클래스 : Exception
    -> IOExcepton, ClassNotFoundException, RuntimeException, ...
  • RuntimeException : Exception의 자손클래스, 주로 프로그래머의 실수에 의해 발생하는 예외들
    1. ArrayIndexOutOfBoundsException : 배열범위 벗어남
    1. NullPointerException : 값이 null인 참조변수 호출
    2. ClassCastExecption : 클래스 간 형변환의 오류
    3. ArithmeticException : 산술연산의 오류(0으로 나눔)
    4. ...
  • Runtime이외에 Exception의 (자손)클래스들 : 외적요인( 사용자의 실수) 등에 의해 발생하는 예외들
    1. FileNotFound : 존재하지 않는 파일 입력
    1. ClassNotFound : 클래스 이름 실수
    2. DataFormatException : 데이터형식 실수

- try - catch - finally : 예외처리하기

try {
	//예외 가능성 있는 실행문들
} catch (Exception1 e1) {
	//Exception1이 발생한 경우 처리하기 위한 문장
} catch (Exception2 e2) {
	//Exception2이 발생한 경우 처리하기 위한 문장
} finally {
	//예외발생 여부와 관계없이 항상 수행되는 문장
    //try - catch의 가장 마지막에 위치
    //선택적!

하나의 try문에서 발생할 수 있는 여러 exception을 처리할 수 있도록
여러 catch문이 올 수 있다.

1. catch블럭 안에서 쓰인 변수는 블럭 안에서만 유효하다
-> 여러 catch문의 변수를 같은 이름으로 설정해도 ok
2. try문 안에 중복으로 try-catch를 사용하는 경우에는 변수이름 중복x
3. 해당 참조변수 통해 에러클래스의 인스턴스에 접근해 메소드 사용 O

- try - catch 문에서의 흐름

  1. try블럭 내에서 오류가 발생한 경우
    : 발생한 오류와 일치하는 catch문을 순서대로 검사 -> catch 블럭 내의 문장 수행 -> ( finally의 문장 수행 -> ) try-catch문 빠져나가서 다음 문장 수행
    : try문 내에서 오류가 발생한 순간, try 내부의 오류문장 밑의 문장은 수행되지 않음
  1. try블럭 내에서 오류가 발생하지 않은 경우
    : catch 거치지 않고 바로 finally의 문장 or try-catch문 빠져나감

발생한 오류와 catch의 참조변수타입 비교하는 방식
: 예외클래스와 참조변수를 instanceof 연산하여 비교
-> 참조변수를 Exception으로 하면 모든 예외를 처리한다.

  • Multi catch 블럭
    : 여러 cathc 블럭을 하나의 catch블럭으로 합칠 수 있다.
    catch( ExceptionA | ExceptionB e )

: A, B 둘 중 하나가 발생하면 해당 catch문으로!
하지만 여러 예외의 참조변수를 하나로 퉁치기때문에
블럭 내부의 실행문에서는 공통분모인 조상예외클래스의 멤버만 사용 가능


- printStackTrace(), getMessage()

  • printStackTrace() : 예외발생 당시의 호출스택의 정보, 예외메세지 출력
    : 예외클래스 인스턴스의 메소드임 -> 참조변수로 호출
try {
	int a = 3/0;
} catch (ArithmeticException ae) {
	ae.printStackTrace(); //클래스의 참조변수 이용해 호출
}
  • getMessage() : 발생한 예외클래스의 인스턴스에 저장된 메세지 얻을 수 있다.

- 예외 발생시키기

throw를 통해 프로그래머가 고의로 예외를 발생시킬 수 있다.

  1. 예외클래스 인스턴스 생성
    : Exception e = new Exception("예외클래스인스턴스에 저장할 메세지");
  2. throw로 예외 발생
    : throw e;

- 메소드에 예외 선언하기

선언부에 throws 키워드, 발생할 수 있는 예외들을 적어주기

리턴타입 메소드이름 throws Exception1, Exception2, ... { ... }

-해당 메소드에 발생할 가능성이 있는 예외들을 파악할 수 있도록 명시하는 기능을 한다.
-> 반드시 처리해야만 하는 예외들만 선언함 (RuntimeException은 x)

- 메소드 예외선언 - 예외처리

메소드에서 발생 가능한 예외를 선언하고
결국 예외를 처리하는 것은 try - catch문이다.

: 메소드 내에서 예외가 발생하고 처리되지 않은 경우,
호출스택대로 자신을 호출한 메소드에 예외를 넘긴다.
-> main메소드까지 처리하지 못하면 비정상적으로 종료

  1. 예외 발생한 메소드 내에서 자체적으로 처리 : 자체적으로 처리 가능한 경우
  2. 호출한 메소드에서 처리(main까지 올라가기도 함)
    : 메소드 내에서 자체적으로 해결 불가한 경우
    : 메소드 호출 시 넘겨받을 인자를 다시 받아야 하는 경우, ...

- 사용자정의 예외

사용자가 직접 새 예외클래스 정의할 수 있다
보통 Exception이나 RuntimeException을 상속받아 만든다

  • Exception 상속 : checked 예외 : 필수적으로 예외처리
  • RuntimeException 상속 : unchecked : 선택적으로 예외처리
class myExc extends Exception {  //Exception을 상속받음
	private final int ERR_CODE; //생성자로 초기화
    
    MyExc(String msg, int errCode) {
    	super(msg); //Exception의 생성자 : 메세지 저장
        ERR_CODE = errCode; //에러코드 저장
    }
    public int getErrCode() { return ERR_CODE; }
}

=>에러메세지, 에러코드 모두 얻을 수 있도록 정의한 사용자정의 예외


- 예외 되던지기

메소드 내에서 발생한 하나의 예외에 대해서
예외가 발생한 메소드, 호출한 메소드 양 쪽에서 처리하게 하는 경우

  1. 예외발생 메소드에서 throw - catch로 예외처리
  2. 예외발생 메소드의 선언부에 thorws 지정
  3. 예외 처리한 catch문에서 throw로 다시 예외 발생시켜 예외전달
static vid method1 throws Exception {
	try {
    	throw new Exception();
    } catch (Exception e) {
    	throw e;
    }
}

- 연결된 예외

한 예외가 다른 예외를 발생시킴

  • 원인예외로 등록하기
  1. initCause(Throwable cause);
  2. RuntimeException 생성자
    : throw new RuntimeExecption(Throwable cause);
  • 원인예외 반환
    getCause();
  • 굳이 원인예외를 등록해 예외를 더 발생시키는 이유
  1. 여러가지 예외를 묶어서 큰 분류의 예외로 다루기 위함
    : spaceException -> InstallException

  2. checked 예외를 unchecked로 바꾸기 위함
    : checked 예외를 선언부에 넣으면 반드시 예외처리 강제됨
    -> 선언부에 넣는 대신 RuntimeException 생성자를 사용해 unchecked로 감싸버린다


    종합예시 연습문제

좋은 웹페이지 즐겨찾기