JAVA

[Java] 예외처리 - throws / try with resources

엘라 ELLA 2022. 10. 18. 17:07
728x90
반응형

기본 try - catch문을 사용해서 예외처리를 하는 방법 말고도, 예외를 메서드에 선언하는 방법도 있다.

 

메서드에 예외를 선언하는 방법은 다음과 같다.

  • 메서드의 선언부에 키워드 throws를 사용해서 메서드 내에 발생할 수 있는 예외를 적어준다.
  • 예외가 여러개 일 경우에는 쉼표(,)로 구분해준다.
void method() throws Exception1, Exception2, ... ExceptionN{
	//메서드의 내용
}

아래와 같이 Exception클래스를 메서드에 선언하면 모든 종류의 예외가 발생 할 가능성이 있다는 뜻이다.

 

Exception클래스는 모든 예외의 최고 조상이기 때문이다.

➜ Exception 클래스 메서드 선언

void method() throws Exception{
	//메서드의 내용
}

하지만, 위와 같이 최고조상의 예외를 선언하게 되면 이 예외 뿐만 아니라 자손타입의 예외까지 발생 할 수 있다.

 

사용 예시

public class ExceptionTest {
    public static void main(String[] args) throws Exception{
        method1();
    }

    static void method1() throws Exception{
        method2();
    }

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

➜ 코드 실행 결과

Exception in thread "main" java.lang.Exception
	at test.ExceptionTest.method2(ExceptionTest.java:13)
	at test.ExceptionTest.method1(ExceptionTest.java:9)
	at test.ExceptionTest.main(ExceptionTest.java:5)

Process finished with exit code 1

 

위 예시 코드에서 아래의 세가지를 알 수 있다.

  • 예외가 발생했을 때, 모두 3개의 메서드가 call stack에 있다.
  • 예외가 발생한 곳은 가장 상단에 있는 method2()이다.
  • main 메소드는 method1()을 호출했고, method1()은 method2()를 호출했다.

실제 프로젝트에서 사용한 코드의 예시이다.

 

실제 코드 예시

  public void sendRegister(CrawlingCrontab dto) throws Exception {
    // 등록 후 에 전송
    try {
      CrawlingInfo one = crawlingInfoRepository.findById(1L).get();
     
     //생략

      OkUrlUtil.post(crawlingUrl, jsonBody.toString());
    } catch (Exception e) {
    
      //생략
      
      throw new Exception(e.getMessage());
    }
  }

 


자동 자원 반환 -try - with - resources

 

JDK 1.7부터 지원하는 try - catch 문의 변형이라고 생각하면 된다.

해당 구문은 입출력(I/O) 관련된 클래스를 사용 할 때 유용하다.

 

➜ DataInputStream을 이용해 파일로부터 데이터를 읽는 코드

try {
	fis = new FileInputStream("score.dat");
    dis = new DataInputStream(fis);
    
    	...
} catch (IOException ie) {
	ie.printStackTrace();
} finally {
	dis.close(); // 작업중 예외가 발생하더라도 dis가 닫히도록 finally 블록에 넣음
}

 

데이터를 읽는 도중에 예외가 생기더라도 DataInputStream이 닫히도록 finally 블럭 안에 close()를 넣어주었다. 하지만, close()가 예외를 발생시킬 수 있다는 점을 놓친 코드이다.

 

➜ 수정된 DataInputStream을 이용해 파일로부터 데이터를 읽는 코드

 

try {
	fis = new FileInputStream("score.dat");
    dis = new DataInputStream(fis);
    
    	...
} catch (IOException ie) {
	ie.printStackTrace();
} finally {
	try{
    	if(dis!=null)
			dis.close(); 
  } catch (IOException ie){
  	ie.printStackTrace();
  }
}

finally 블럭 안에 try - catch 문을 추가해서 close()에서 발생 할 수 있는 예외를 처리해주는것이다. 이 코드에서도 헛점은 존재하는데 try 블럭과 finally 블럭에서 모두 예외가 발생한다면, try블럭의 예외는 처리되지 않고 넘어간다.

 

이런 점을 개선하기 위해서 try - with - resources문을 사용하면 된다.

try - with - resources문으로 수정한 DataInputStream을 이용해 파일로부터 데이터를 읽는 코드

try (FileInputStream fis = new FileInputStream("score.dat");
	DataInputStream dis = new DataInputStream(fis)) {
    
    while(true){
    	score = dis.readInt();
        System.out.println(score);
        sum += score;
    }
} catch (EOFEcxeption e) {
	System.out.println("점수의 총합은" + sum + "입니다.");
} catch (IOException ie) {
	ie.printStackTrace();
}

 

try - with - resources문의 괄호안에 객체를 생성하는 문장을 넣으면, 이 객체는 따로 close()를 호출하지 않아도 try블럭을 벗어나는 순간 자동적으로 close()를 호출한다. 후에 catch블럭이나 finally블럭이 실행된다.


게시글이 도움이 되었다면

[로그인]이 필요 없는 ❤ 눌러주세요:)

 
 
반응형