본문 바로가기

자바의 정석 정리

자바의 정석 - 8.2 예외 발생시키기

8.2.1 예외 발생방법

  1. new 연산자를 통해 예외 클래스의 객체 생성
  2. 키워드 throw를 통해 예외 발생
class A{
    public static void main(String[] args){
    try{
        Exception e = new Exception("고의 발생");
        throw e;
        //throw new Exception e;
    }catch(Exception e){
        e.printStackTrace();
    }
}

//컴파일 실패
//checked 예외
class A{
    public static void main(String[] args){
        throw new Exception(); //try-catch로 에러처리를 하지않아 에러 발생
    }
}

//컴파일 성공
//하지만 런타임때 에러
//unchecked 예외
class A{
    public static void main(String[] args){
        throw new RuntimeException(); //try-catch로 에러처리를 하지않아 에러 발생
    }
}

8.2.2 메서드에 예외 선언하기

  • 메서드 내부에서 발생할 수 있는 예외를 선언부에 'throws'를 통해서 선언
  • 예외가 여러개 있을 경우 콤마(,)로 구분
void method throws Exception1, Exception2, ...{}

8.2.3 Object클래스의 wait()메서드 예외

  • wait()메서드에는 IllegalMonitorStateException과 InterruptedException 예외가 존재함
  • IllegalMonitorStateException : Exception의 자식
  • InterruptedException : RuntimeException의 자식

8.2.4 예외 전달하기

  • 메서드 선언부에 throws를 통해 예외를 던짐
  • 메서드를 선언한 곳에 예외를 전달하여 예외 책임을 떠넘김
public static void main(String[] args){
    try{
        callMethod();
    }catch(Exception e){
    }
}

static void callMethod() throws Exception{
    throw new Exception();
}

8.2.5 finally 블럭

  • 예외에 상관없이 무조건 실행
  • 주로 finally에서 '파일 닫음'과 같이 자원을 반환해 주는 코드를 작성한다.
try{
}catch(Exception e){
}finally{
}
  • try내부에 return이 있어도 finally가 실행되고 나서 return이 실행 됨
try{
    return null;
}catch(Exception e){
}finally{
    System.out.println("final");
}

/*
final이 출력 된 이우에 null이 return됨
*/

8.2.6 자동 자원 반환(try-with-resource)

  • 자원을 반환(.close)에서 오류가 날 수 있으므로 finally는 그다지 안전하지 않다.
  • try-with-resource를 사용하여 .close를 호출하지 않아도 자동적으로 호출됨
try(FileInputStream fis = new FileInputStream("score.txt");
        DataInputStream dis = new DataInputStream(fis)){

}catch(Exception e){
}

/*
자동으로 close가 호출되어서 자원 반환을 한다.
*/

8.2.7 억제된 예외

  • 메서드 내부에서 두개 이상의 예외가 발생했을 때
  • 두 예외가 동시에 발생할 수 없기 때문에, 한 예외 내부에 다른 예외가 저장(억제, suppressed)됨

8.2.8 연결된 예외(chained exception)

  • 예외 A가 예외 B를 발생시켰다면, A를 원인 예외(cause exception)라 한다.
try{
}catch(SpaceException e){
    InstallException ie = new InstallException("설치 중 예외 발생");
    ie.initCause(e); //SpaceException를 원인 예외로 지정
    throw ie;
}

연결된 예외 사용 이유

  1. 조상 예외를 사용하면 실제 예외가 어떤 것인지 확인 불가(또한, 조상 예외로 처리를 하면 에러 발생)
  2. try{ }catch(InstallException e){} /* InstallException은 SpaceException과 MemoryException의 조상 */
  3. checked 에러를 unchecked로 전환
  4. //checked에러 static void startInstall() throws SpaceException, MemoryException{ if(!enoughMemory) { throw new MemoryException("메모리 부족"); } } //unchecked에러 static void startInstall() throws SpaceException{ if(!enoughMemory) { throw new RuntimeException(new MemoryException("메모리 부족")); } }