가자미의 개발이야기

자바의 예외처리 try catch, throw 본문

Java/자바 기본 문법

자바의 예외처리 try catch, throw

가자미 2021. 1. 11. 18:05

a. 에러와 예외

에러 : 프로그램 코드에 의해서 수습될 수 없는 심각한 오류

예외 : 프로그램 코드에 의해 수습될 수 있는 미약한 오류

 

b. 에러의 종류

컴파일 에러 : 컴파일 시 발생

런타임 에러 : 실행 시에 발생

논리적 에러 : 의도와 다르게 실행

 

c. 예외 클래스의 계층 구조

  1. Exception클래스와 그 자손들
  2. RuntimeException클래스와 그 자손들

Exception클래스들 : 사용자의 실수. 외적인 요인에 의해 발생

RuntimeException클래스들 : 프로그래머의 실수로 발생

 

이렇게 두가지로 예외 클래스를 분류할 수 있음.

 

d. try catch

예외 발생에 대비한 코드 작성.

프로그램의 비정상 종료를 방지. 정상적 실행 상태 유지

try {

    관찰 영역

}

catch(예외 클래스 e){

    처리 영역

}

finally {

    예외 발생과 관련 없이 무조건 실행되는 영역

}

try 관찰영역에서 발생한 예외 클래스의 인스턴스를 catch 의 인수로 전달되어 처리영역으로 실행된다.

try 관찰영역에서 예외가 발생해서 catch로 예외처리 될 경우 try 관찰영역의 나머지 부분은 실행되지 않고 넘어간다.

 

다수의 catch는 매개변수를  catch(예외 클래스 | 예외클래스 e)로 해결 할 수 있거나, 연달아 catch 블록을 만들어 예외처리 할 수 있다. 

try{
    ....
} catch (ExceptionA | ExceptionB e) {
        e.printStackTrace();
}

try{
    ....
} catch (ExceptionA e){
    e.printStackTrace();
} catch (ExceptionB e){
    e.printStackTrace();
}

e. printStackTrace(), getMessage()

printStackTrace : 예외 발생 당시의 호출 스택에 있었던 메소드의 정보와 예외 메시지를 화면에 출력

(예외 발생한 위치와 메소드 내용을 출력)

getMessage : 발생한 예외 클래스의 인스턴스와 저장된 메시지를 얻음

(오류 내용을 문자열로 반환)

 

f. 예외 발생시키기

  1. 예외 클래스의 객체를 new 연산자로 만들기
  2. 키워드 throw를 이용해서 예외 발생시키기
Exception e = new Exception("고의로 발생");
throw e;

#try with resources

괄호 안의 명령문은 try가 끝나고 나면 자동으로 close를 해준다.

try(BufferedWriter writer =Files.newBufferedWriter(file)){
    ....
}cathch(ExceptionA e){
    e.printStackTrace();
}

이런식으로 리소스 open과 close를 자동으로 해결해준다.

 

g. 메소드에 예외 선언하기

메소드에 예외를 선언하면 그 자손 타입의 예외까지도 발생할 수 있다.

오버라이딩할 때는 단순히 선언된 예외의 개수가 아니라 상속 관계까지 고려해야한다.

메소드의 선언부를 보면 프로그래머가 어떤 예외가 발생할지 예상할 수 있다.

void methodName() throws Exception1, Exception2...{
    //메소드 내용
}

void methodName2() throws Exception{
    //메소드 내용
}

 

h. 사용자 정의 예외 만들기

기존의 예외 클래스 외에 프로그래머가 새로운 예외 클래스를 만들 수 있다.

class MyExceptiono extends Exception {
    //에러코드 값을 저장하기 위한 필드를 추가
    private final int ERR_CODE;	//생성자를 통해 초기화
    
    MyException(String msg, int errCode){//생성자
    	super(msg);//조상인 Exception클래스의 생성자를 호출. msg를 메시지로 저장
        ERR_CODE = errCode;
    }
    
    MyException(String msg){//생성자
        this(msg, 100);//에러코드 100으로 초기화
    }
    
    public int getErrCode() {
        return ERR_CODE;
    }
}

i. 예외 되던지기

예외가 발생한 메서드와 호출한 메서드 양쪽에서 예외를 처리하는 것

예외를 처리한 후에 인위적으로 다시 발생시키는 방법.

 

하나의 예외에 대해서 예외가 발생한 메서드와 이를 호출한 메서드 양쪽 모두에서 처리해줘야 할 작업이 있을 때 사용.

class Ex8{
    public static void main(String[] args){
    
        try{
            method1();//예외가 발생하도록 하는 메소드를 호출
        } catch(Exception e){
            e.printStackTrace();
        }
    }
    
    static void method1() throws Exception{
        try{
            throw new Exception();//고의적으로 예외를 발생
        } catch (Exception e){
            e.printStackTrace();
            throw e; //main에서 catch되도록 예외를 일으키는 모습
        }
    }
}

j. 연결된 예외

예외 A가 예외 B를 발생시킬 경우,

예외 A는 원인 예외라 한다.

try {
    startInstall(); //SpaceException발생
    copyFiles();
    } catch (SpaceException e){
        InstallException ie = new InstallException("설치중 예외 발생");//예외발생
        ie.initCause(e); //InstallException의 원인 예외를 SpaceException으로 지정
        throw ie; //InstallException을 발생시킴
    } ....

SpaceException 발생 - InstallException 생성 - InstallException의 원인 예외를 SpaceException으로 설정 - InstallException을 throw.

 

Throwable initCause(Throwable cause) 지정한 예외를 원인 예외로 등록

Throwable getCause() 원인예외를 반환

 

왜 연결된 예외를 설정하는가?

  1. 하나의 큰 분류의 예외로 묶어서 다루기 위함
  2. checked 예외(Exception클래스, 컴파일조차 안되는 예외)를 unchecked 예외(RuntimeException클래스, 컴파일은 되는 예외)로 만들기 위함
    checked 예외는 반드시 예외처리를 해야하는 예외이고, unchecked 예외는 선택적으로 해야하는 예외인데,
    굳이 예외처리를 안해도 되는 예외가 checked 예외인 경우, RuntimeException으로 감싸버리면 된다.
    //RuntimeException(Throwable cause) 원인 예외를 등록하는 생성자.
    throw new RuntimeException(new MemoryException("메모리가 부족.."));​