본문 바로가기

Java/기본

[Java] 예외처리 - 예외 처리하기

예외를 처리하는 방법은 2가지다.

1) try ~ catch 문으로 처리하는 방법

2) 예외객체를 throws 문으로 전달하는 방법


try ~ catch

문법은 아래와 같다. try{ } 안에 있는 코드를 한 줄 씩 수행하다가 예외가 발생하는 코드를 만나면 catch{ } 문으로 이동한다. 예외를 만나면 그 아래에 있는 코드는 실행되지 못한다.

syntax try{
     //예외 발생 코드
} catch(예상되는예외객체 변수명){
     //예외 발생시 수행되는 코드
}

 

public class NullPointerEx {
	public static void main(String[] args) {
    
		String str1 = "test";
		String str2 = null;		
		String str2 = "test2";		
				
		try {
			System.out.println(str1,toString);	//정상실행
			System.out.println(str2.toString);	//예외발생
			System.out.println(str2.toString);	//실행안됨
			//객체(인스턴스)가 없는데 인스턴스에 있는
			//toString()메소드를 호출시도하여 예외 발생함
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}
}

 

다중 catch 문

다중 catch문은 하나의 try 문에서 여러 예외상황이 발생할 경우에 사용한다. 여러 catch문을 사용해 다양한 예외를 잡을 목적으로 사용한다. 예외가 발생하는 경우 나열된 catch 순서대로 작성된 예외객체와 비교해가면서 수행될 코드를 찾아가게 된다. 예외 중 가장 상위 클래스는 Exception이다. 모든 예외를 처리할 수 있기 때문에 catch 문 가장 하단에 위치하여 상단에서 잡지 못하는 예외를 최종적으로 잡는다. 예외상황의 최종관문이라고 기억해두자.

public class MultiCatchEx {
	public static void main(String[] args) {	
		try{			
			int[] intArr = new int[5];
			int[] intArr2 = null;
			
			//ArrayIndexOutOfBoundsException 발생
			for(int i=0; i<6; i++) {
				intArr[i] = i;
			}
			
			//ArithmeticException 발생
			intArr[0] = 100/0;
			
			//NullPointerException 발생
			System.out.println(intArr2.toString());
			
		} catch (ArrayIndexOutOfBoundsException arrayOBE) {
			arrayOBE.getMessage();
		} catch (ArithmeticException ame) {
			ame.getMessage();
		} catch (NullPointerException npe) {
			npe.getMessage();
		} catch (Exception e) {
			e.getMessage();
		} 		
	}
}

 

finally{ }

 

finally{} 영역에 있는 코드는 예외발생에 상관없이 항상 수행되는 영역이다. try영역 수행중 발생한 예외를 해결하고 난뒤 반드시 수행되어야하는 코드가 finally 영역에 기술된다.

주로 database 연결후 자원을 해제하는 코드에 많이 사용되는 코드이다.


throws

throws 는 예외가 발생하는 경우 이를 처리할 역할을 전달할 필요가 있을 떄 사용한다. 예외가 발생하는 코드를 호출한 곳으로 예외객체를 전달하여 처리를 부탁하는 것이라고 보면된다.

 

public class MultiCatchEx {
	public static void main(String[] args) {			
		try {			
			int x = changeToInteger("test");
			int y = printArrayElement(new int[] {1, 2, 3}, 5);		
		} catch (NumberFormatException nfe){
			nfe.getMessage();
		} catch (ArrayIndexOutOfBoundsException aiob) {
			aiob.getMessage();
		} catch (Exception e) {
			e.getMessage();
		}
	}	
	static int changeToInteger(String str) throws NumberFormatException{
		int number = Integer.parseInt(str);
		return number;
	}	
	static int printArrayElement(int[] intArr, int index) throws ArrayIndexOutOfBoundsException{
		int number = intArr[index];
		return number;
	}
}

 

예제 코드를 보면 changeToInteger() 메서드와 printArrayElement() 메서드 수행시 예외가 발생하면 호출한 곳에서

예외를 처리하도록 역할을 양도하고 있다. main 함수에서 두 함수를 호출하고 있으므로 해당 예외를 처리하는

코드를 작성했다.

 

 

사실 위 예제코드에서도 예외를 양도할 수 있다. 바로 JVM에 예외처리 역할을 넘기는 것이다.

아래 코드를 보면 메서드를 호출하면서 발생한 예외를 다시 JVM에 양도하는 것을 볼 수 있다.

 

public class MultiCatchEx {
	public static void main(String[] args) throws Exception {		
		int x = changeToInteger("test");
		int y = printArrayElement(new int[] {1, 2, 3}, 5);		
	}	
	static int changeToInteger(String str) throws NumberFormatException{
		int number = Integer.parseInt(str);
		return number;
	}	
	static int printArrayElement(int[] intArr, int index) throws ArrayIndexOutOfBoundsException{
		int number = intArr[index];
		return number;
	}
}

 

 

 

throws를 사용한 예외객체의 양도는 예외처리와는 다르다. 예외처리할 역할을 해당 코드를 호출한 곳으로 위임하는 것이기 때문에 정상적으로 코드가 실행되기 위해서는 try ~ catch문으로 예외를 적절히 해결해야한다.

 

그럼에도 throws 코드가 존재하는 이유는, try~catch 문 수행시 내부에서 과도한 로직처리를 막기위해서이다.

예외처리코드가 많은 경우 이를 처리하는 과정에서 과부하가 발생할 수 있다. 이를 방지하기 위해 예외처리코드를 양도한 뒤에, 최종 호출하는 곳에서 try~catch 문으로 한번에 처리해 프로그램이 무거워지지 않도록 하기 위함이다.