본문 바로가기
프로그래밍/java

java 예외처리 정리 (try-catch, finally, throws, throw)

by 뜨끔쓰 2019. 4. 24.
728x90
728x90

안녕하세요


이번시간에는 java의 예외처리에 대하여 공부하고 정리해볼 시간을 가져볼려고합니다.


우선 기본적으로 예외처리가 왜 필요할까요? 저도 처음 프로그래밍을 배울때 예외처리가 왜 필요한지 몰랐었습니다.


완벽한 프로그램으로 만들면 되는거아니야?? 라고 생각했으나 이건 정말 저의 크나큰 오산이였습니다.


if문도 예외처리의 한 방법이 될 수 있기 때문에 저는 그렇게 생각했으나, if문만으로는 처리하기 힘든 문제들이 산더미 같더라구요..


그래서 예외처리가 필요하구나! 하고 직접 예외처리를 써보기 시작했더니, 아니 프로그래밍이 이렇게 편할 수가 있는건가요? 생각이 들더군요.


자 그럼 서론은 이쯤하고, 직접 예외처리에는 무엇이있고 어떻게 사용하는지 알아보도록하겠습니다.



예외처리란?

일단 예외란 프로그래밍 소스코드를 작성하여 컴파일과정에서는 문제를 발견하지 못하고 정상적으로 컴파일이 진행되었으나, 프로그램을 실행중에 발생하는 오류사항들을 대체로 예외라고 정의합니다.

ex) 범위를 넘어선 배열접근, 정수를 0으로 나누는 경우, Null포인터 오류등이 있습니다. 

그럼 이러한 오류가 발생하면 개발자는 어떻게 처리를 해주어야 하느냐? 

처리하는 방법에는 여러가지가 있겠는데 어떤 에러가 발생할지 알고 있다면 Excepiton클래스명을 직접 명시해주거나 아니면 Excepiton을 통해 한꺼번에 처리해주는 방법이 있을 수 있습니다.

try ~ catch문을 사용하는 방법부터 확인해보겠습니다.

기본적으로 try ~ catch문의 구조는 아래와 같아요.

try {
     예외가 생길 가능성이 있는 코드 작성
} catch(예외발생 클래스명 e){
     예외처리 코드
}
여기서 마지막에 finally를 추가하거나 하는 방법이 있지만 이건 더 아래에서 정리하도록 하겠습니다.

소스코드를 보며 확인해보도록 할께요.

public class Mathematics { public static void main(String[] args){ int num1, num2; num1 = 12; num2 = 0; try { System.out.println(num1/num2); } catch (Exception e) { System.out.println("0으로는 값을 나눌 수가 없습니다."); } } }

소스코드를 보시면 num1과 num2에 각각 12, 0의 값을 대입 해주었죠?

결과를 한번 보실까요?

이렇게 catch부분에서 처리해준 소스코드가 출력 되죠??

그렇다면 try 부분에서 num1(12)을 num2(0)로 나눠주고 있는데 이부분에서 try~catch문을 사용하지 않는다면 어떻게 될까요??

이런식으로 ArithmeticException 이라고 뜨면서 에러가 발생하게 될꺼에요!

나눗셈을 할때 정수를 0으로 나눌때는 어떤 에러가 발생하는지 알게 되었죠? 그러면 try catch문을 아래처럼 작성 하실 수 있어요.

public class Mathematics { public static void main(String[] args) { int num1, num2; num1 = 12; num2 = 0; try { System.out.println(num1/num2); } catch (ArithmeticException e) { System.out.println("0으로는 값을 나눌 수가 없습니다."); } } }

이런식으로 직접적으로 어떤 error가 발생하는지 Excepiton의 클래스명을 알고있다면 각각에 에러에 대하여 예외처리를 해주실 수 있어요.

그렇다면 여러 에러가 발생 할 가능성을 가지고 각각의 에러에 대하여 예외처리 구문을 작성해줄수도 있겠죠?


public class Mathematics {
  public static void main(String[] args) {
       int num1, num2;
       int [] intArrayList = {0, 1, 2};
       
       num1 = 12;
       num2 = 0;
       
       try {
            //System.out.println(num1/num2);
            System.out.println(intArrayList[3]);
       } catch (ArithmeticException e) {
            System.out.println("0으로는 값을 나눌 수가 없습니다.");
       } catch (ArrayIndexOutOfBoundsException e) {
       	    System.out.println("배열의 범위를 넘어섰습니다.");
       }
  }
}

이번에는 보시면 try부분에 있는 num1/num2부분은 주석처리 하였습니다. 그이유는 처음 에러가 발생하여 예외처리를 하는 경우 try구문안에 있는 그다음은 실행하지 않기 때문입니다. 

보시면 intArrayList라는 변수는 길이가3인 배열입니다. 그치만 try구문에서는 intArrayList[3]에 접근하고 있습니다. 

이렇게 존재하지 않는 배열에 접근하게 되는 경우 ArrayIndexOutOfBoundsException이 발생하여 catch문으로 이동하여 "배열의 범위를 넘어섰습니다."가 출력될것입니다.

그렇다면 예외가 발생했던 안했던 어떤 소스코드를 실행해주고싶다! 

라는 생각이 드실 수 있잖아요? 바로 그럴때 finally를 사용하시면 됩니다.

public class Mathematics { public static void main(String[] args) { int num1, num2; int [] intArrayList = {0, 1, 2}; num1 = 12; num2 = 0; try { //System.out.println(num1/num2); System.out.println(intArrayList[3]); } catch (ArithmeticException e) { System.out.println("0으로는 값을 나눌 수가 없습니다."); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("배열의 범위를 넘어섰습니다."); } finally { System.out.println("헤헷 나는 finally야!"); } } }

이런식으로 작성해주시면 finally의 "헤헷 나는 finally야!"라는 아웃풋이 실행됩니다.

지금까지 try ~ catch문을 알아보았는데요. 이해가 되셨을까요?? 

다음은 throws입니다.





throws란?

한마디로 하자면 "자신을 호출하는 메소드에 예외처리의 책임을 넘긴다" 라고 생각하시면됩니다.
예제 코드를 보며 정리하는게 더 도움이 될 것 같아 우선 예제부터 보도록하겠습니다.

public class Main { public static void nanum(int a, int b) throws ArithmeticException { System.out.println(a/b); } public static void main(String[] args) { int num1, num2; num1 = 10; num2 = 0; try { nanum(num1,num2); } catch (ArithmeticException e){ System.out.println("0으로 나눌 수는 없어요.."); } } }


보시면 nanum이라는 메소드 뒤에 thorws ArithmeticException 부분이 보이시죠? 이렇게 사용하는건데 ArithmeticException 예외가 발생하면

<이 메소드를 사용하는곳에서 예외처리를 넘겨주라는 뜻이 됩니다.

그래서 main부분에서 nanum메소드를 호출할때 try-catch문을 이용하여 예외처리를 해주었죠?

결과는 아래와 같이 나옵니다.

정상적으로 예외처리가 되었죠?

그런데 굳이 왜 try-catch를 진작에 써도 되는데 throws를 이용하여 두번 일하게 만드느냐?!

한가지 예외상황에 대해 각각 불러오는 곳에서 다른 방법으로 예외처리를 하고싶을때 사용합니다.

이외에도 여러 이유가 있겠지만 제가 생각하기엔 위의 이유가 제일 크다고 봅니다.


다음은 throw입니다.




throw란?

throws랑 throw는 s하나차이지만 쓰임새는 확 달라지게 됩니다.

우선 throw에 대하여 설명하자면 "개발자가 직접 사용자정의 예외를 발생시키고싶다." 사용합니다.

예제코드로 확인해볼께요!


public class Main {

	public static void throwExample() throws Exception {
		throw new Exception();
	}
	public static void main(String[] args) {
		try {
			throwExample();
		} catch (Exception e){
			System.out.println("예외가 발생했습니다...");
		}
	}
}


직접 이코드에서 try-catch문을 빼고 throwExample() 메소드를 호출하면 에러가 발생하실꺼에요. 그렇기 때문에 이런식으로 사용자가 직접 예외를 발생시켜주고싶은 부분에 throw new Excepiton();을 통하여 예외를 발생시켜주고 throws를 통하여 예외처리를 던져줍니다.

그러면 main에서 throwExample 메소드를 호출할때 예외처리를 해주어야하겠죠? 바로 이런방식입니다. 결과를 한번 보실까요.

정상적으로 잘 처리되었죠?? throw는 이렇게 사용자가 직접 예외를 발생하고 싶은곳에 쓰셔서 사용하시면됩니다.



이번에는 예외처리 (try-catch, finally, throws, throw)에 대하여 알아보았는데요

정리가 잘 되었을까요?? 프로그래밍을 배우면서 제일 중요한건 프로그램이 구동돼서 문제 없이 잘 돌아가는게 목표라고 생각됩니다.

그러기 위해선 예외가 발생하는 부분을 잘 처리해주어야 제대로 된 프로그램으로 완성이 되기때문에 java의 이 예외처리부분은 상당히 중요합니다.

프로그램을 작성함에 있어서 모든 문제를 한번에 발견하면 좋겠지만 그러기는 쉽지 않기 때문에 최대한 소스코드를 작성할때 에러가 생기겠다 싶은 부분은 다 예외처리를 통하여 매끄럽게 소스코드를 구성하며 직접 테스트를 통하여 문제가 되는 부분을 수정하면 한 단계 높은 프로그래머가 될 수 있을거라고 생각합니다. 저도 아직 공부하는 입장이기때문에 글에서 부족한 부분이 있을때는 언제든 댓글로 수정 및 의견 부탁드리겠습니다.


감사합니다.

728x90
반응형

댓글