본문 바로가기

DEVELOPER/Java

Java의 예외 처리하기 - Exception

반응형

프로그램에서의 오류


· 컴파일 오류(compile error)

프로그램 코드 작성 중 발생하는 문법적 오류

최근에는 개발 환경(eclipse, intelliJ)에서 대부분의 컴파일 오류는 detection 됨.


· 실행 오류(runtime error)

실행 중인 프로그램이 의도하지 않은 동작(bug)을 하거나 프로그램이 중지되는 오류

실행 오류는 비정상 종료 되는 경우 시스템의 심각한 장애를 발생 가능


 

예외 처리의 중요성


  • 프로그램의 비정상 종료를 피하여 시스템이 원할이 실행되도록 함
  • 실행 오류가 발생한 경우 오류의 과정을 재현하는 것은 현식적으로 힘듦
  • 오류가 발생한 경우 log를 남겨서 추후 log 분석을 통해 그 원인을 파악하여 bug를 수정
자바는 안정성이 중요한 언어로 대부분 프로그램에서 발생하는 오류에 대해 문법적으로 예외 처리를 해야 함

오류와 예외 클래스


① 시스템 오류 (error) : 가상 머신에서 발생, 프로그래머가 처리할 수 없는 오류

ex. 동적 메모리가 없는 경우, 스택 메모리 오버플로우 등

② 예외(Exception) : 프로그램에서 제어할 수 있는 오류

ex. 읽어 들이려는 파일이 존재하지 않거나, 네트워크이나 DB 연결이 안 되는 경우 등

Throwable Class에서 상속 받는 Error, Exception

예외 클래스들


모든 예외 클래스의 최상위 클래스는 Exception 클래스

 


다양한 예외 처리 클래스

위에 명시된 클래스보다 더 많은 예외 처리 클래스 존재

 


예외 처리하기


try-catch 문


  • try 블록에는 예외가 발생할 가능성이 있는 코드를 작성
  • try 블록 안에서 예외가 발생하는 경우 catch 블록 수행

 

try-catch 문

 


배열의 오류 처리 예제

배열의 index보다 더 많이 실행했을 경우 오류 발생

public class ArrayIndexException {

	public static void main(String[] args) {
    
    int[] arr = {1,2,3,4,5};
    
    //원래는 i<5 이어야 오류가 없다.
    for(int i=0; i<=5; i++) {
				System.out.println(arr[i]);
			} 
    System.out.println("here!!");
}

위처럼 코드를 구현했을 때..


오류 발생

length가 5이면 index는 4까지만 호출되어야 하는데 넘어버렸다는 오류 발생

∴ 오류로 인해 코드가 끝가지 실행이 되지 않아서, here!! 메시지는 호출되지 않음


public class ArrayIndexException {

	public static void main(String[] args) {

		int[] arr = {1,2,3,4,5};
		
		try {
			for(int i=0; i<=5; i++) {
				System.out.println(arr[i]);
			}
		}catch(ArrayIndexOutOfBoundsException e) {
			System.out.println(e.getMessage());
			System.out.println(e.toString());
		}
		
		System.out.println("here!");
	}

}

이번엔 try-catch 문을 이용하여 ArrayIndexOutOfBoundsException 예외를 처리해준다.


예외 처리에 대한 결과

  • 중간에 예외가 발생해도 코드는 끝까지 실행되어 here! 메시지를 호출
  • getMessage( ) 메서드를 통해 에러 원인 메서지 호출
  • toString( ) 메서드는 Exception의 풀네임과 메세지를 호출

 

try-catch-finally 문


단순히 try-catch문으로만 Exception을 핸들링할 때

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileExceptionHandling {

	public static void main(String[] args) {

		FileInputStream fis = null;
		//add throws exception -> 내가 처리안하고 던진다는 의미(throws FileNotFoundException)
		//Surround with try/catch
		
		try {
			fis = new FileInputStream("a.txt");
			System.out.println("read");
			
			try {
				fis.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		} catch (FileNotFoundException e) {

			e.printStackTrace(); //어디서 error가 생겼는지 trace
			System.out.println(e);
			
			try {
				fis.close();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
		
		System.out.println("end");

	}

}

매우 복잡하다.

 


try-catch-finally문으로 변환

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileExceptionHandling {

	public static void main(String[] args) {

		FileInputStream fis = null;
		//add throws exception -> 내가 처리안하고 던진다는 의미(throws FileNotFoundException)
		//Surround with try/catch
		
		try {
			fis = new FileInputStream("a.txt");
			System.out.println("read");	
		} catch (FileNotFoundException e) {

			e.printStackTrace(); //어디서 error가 생겼는지 trace
			System.out.println(e);	
		} finally {
			
			if(fis != null) {
				try {
					fis. close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			System.out.println("finally");
		}
		//finally는 항상 불린다.
		System.out.println("end");

	}

}
  • try구문이 호출이 됐을 때 finally는 항상 실행이 된다.

더 간단하게는..

try-with-resources문

Java 7부터 가능한 구문
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileExceptionHandling2 {

	public static void main(String[] args) {

	
		try(FileInputStream fis = new FileInputStream("a.txt")) {

			System.out.println("read");
						
		} catch (FileNotFoundException e) {
//		FileNotFoundException은 파일이 없을 때 처리되는 Exception
			
			e.printStackTrace();
		} catch (IOException e) {
//		close할 때 처리되는 Exception
			
			e.printStackTrace();
		}
		
		System.out.println("end");

	}

}
  • try( ) 내부에서 리소스를 선언
  • 리소스를 사용하는 경우 close( )를 명시적으로 하지 않아도 자동으로 해제됨
  • 해당 리소스 클래스가 AutoCloseable 인터페이스를 구현해야 함
  • 위 코드에서 FileInputStream은 AutoCloseable을 구현하고 있음
  • Java 9부터 리소스는 try( ) 외부에서 선언하고 변수만을 try(obj)와 같이 사용 가능

 

AutoCloseable을 구현


① AutoCloseable을 구현한 클래스

public class AutoCloseableObj implements AutoCloseable {

	@override
    public void close() throws Exception {
    
    	System.out.println("closing...");
    }
}

 

 

② try-with-resource 방식으로 실행

public class AutoCloseTest {

	public static void main(String[] args) {

		AutoCloseableObj obj = new AutoCloseableObj();
		
		try(obj) {
			
		} catch(Exception e) {
			System.out.println("exception");
		}
		
		System.out.println("end");
	}
	
}
  • AutoCloseable을 구현한 클래스로 객체를 생성 후
  • try( ) 내부에 변수를 넣는다.
  • try( ) 구문에는 아무것도 없기 때문에 catch에 걸리지 않고 close( )를 자동으로 진행 후 end

결과

 

public class AutoCloseTest {

	public static void main(String[] args) {

		AutoCloseableObj obj = new AutoCloseableObj();
		
		try(obj) {
			throw new Exception(); //exception 강제 발생(생성)
			
		} catch(Exception e) {
			System.out.println("exception");
		}
		
		System.out.println("end");
	}
	
}
throw new Exception( ); 은 exception을 강제 발생

exception 처리 후 end 결과

반응형

'DEVELOPER > Java' 카테고리의 다른 글

자바의 예외 처리 - 로그 남기기(log)  (0) 2021.05.09
예외 처리 미루기  (0) 2021.05.08
reduce( ) 연산  (0) 2021.05.07
스트림(Stream)  (0) 2021.05.06
람다식(Lambda expression)  (0) 2021.05.05