2011년 4월 27일 수요일

자바의 제어문(try)


우리가 프로그램을 만들다 보면 오류가 생길때가 있다. 이럴 경우 우리가 잡을수 있는 오류랑 우리가 잡을수 없는 오류로 나누어지는데 우리가 고칠수 있는 대부분의 오류를 Exception이라고 하고 우리가 잡기 힘든 오류를 말그대로 Error라 한다. Error는 메모리 문제라든가 치명적인 에러라 쉽게 고칠수 있는 부분이 아니지만 Exception에 관계된 오류는 우리가 프로그램으로 커버가 가능하다. 우리는 우리가 할수있는것(?)만 잡아보기로 하자.

자바의 예외처리 구문을 상당히 어려워하는 이가 많다. 평상시 코드의 수정으로 인해 대부분 극복이 되니 지나칠수도 있고 일단 용어(?) 자체가 굉장히 생소하고 영어가 무진장 길다.ㅎㅎ 그래서 특히나 어려워하는지도......아닌감?? 그러나 두려워하지 말자. 오늘 차근차근 공부하다보면 어느새 여러분은 이런 오류가 나도 덤덤해질테니까 말이다.^^

Exception은 try catch 구문으로 잡을수 있는 비교적 작은 에러를 말하는 것으로 우리는 제어문에서 이를 예외처리(Exception Control)라 부른다. 보통 프로그램을 짜다가 자주 접하는 예외는 RuntimeException이라고 부르는 오류인데 아마 예제를 실행하다가 한번쯤 접해봤을지도 모르겠다. 컴파일은 되는데 작동이 안되는 경우다. 이런건 대부분 코딩을 잘못해서 생기는 문제이니 이런 예외가 발생하면 프로그램에서 잘못된 코드는 없는지 살펴보기 바란다. 대부분의 오류가 코딩시 잘못되어 발생하는 문제이지만 상황에 따라서 try catch 구문을 사용해야만 하는 경우가 생기는데 자바에서 이런 예외를 어떻게 다룰수 있는지 집중적으로 알아보도록 하겠다.

try
{
//예외가 발생하는 부분을 try 블록으로 감싸준다.
}

catch (?Exception e) //괄호안에는 exception 예외 종류를 써준다.
{
명령문1; //예외가 발생했을때 실행할 부분을 적어준다.
...
}

catch (??Exception e) //예외를 하나만 잡을수 있는건 아니다.
{
명령문2; //예외가 발생했을때 명령처리할 부분이다.
...
}

catch (???Exception e)
{
명령문3; //예외 발생시 명령 처리한다.
...
}

..
...
....//catch 구문은 여러개가 가능하다.

finally
{
명령문5;
...
}

finally 구문은 try catch 다음의 맨 아래에 위치하며 예외가 일어나든 말든 무조건 실행된다. catch나 finally 구문은 없어도 된다. 허나 둘중 하나는 반드시 있어야 한다. 단지 꼭 실행해야할 명령이 있을때 사용하면 된다. 조금더 자세히 설명하자면 try 블록에서 예외가 일어난다. 당연히 그래서 try 블록을 그곳에 감싸놓게 될것이다. catch는 바로 이 try 블록에서 어떤 exception 오류가 나는거에 따라 결정된다. 즉 첫번째 catch 구문에 적어놓은 ?Exception이 발생할경우 명령문2를 실행하고 finally 블록의 명령문5를 실행한다.(finally 구문은 무조건 실행된다.) 만약 try 블록에서 세번째 catch 구문에 적어놓은 ???Exception이 발생했다면 명령문3를 실행하고 finally 블록의 명령문5를 실행한다. 다 이해했겠지만 예제를 통해서 다시 한번 알아보자.


위의 예제는 배열을 이용한 것이다. 변수 a에는 하나의 숫자만 들어가지만 배열을 이용하면 여러개의 요소들을 집어넣고 필요할때 빼서 쓸수가 있다. 예전 입출력 예제에서 잠시 언급한 적이 있을텐데 프로그램을 설명하자면 a[0]이라는 공간에 1이 들어가고 a[1]에는 2가 a[2]에는 3이라는 숫자가 들어가는 배열이다. [ ]안을 a라는 공간의 한 지점(index)이라고 생각하면 이해가 쉬울것이다. 창고 a가 있는데 0번방에는 숫자 1을 1번방에는 숫자 2를... 뭐 이런식으로 생각하면 된다.

int[ ] a=new int[3];
a[0]=1;
a[1]=2;
a[2]=3;

int[ ] a={1,2,3}; 이라는 명령은 a[0]=1, a[1]=2, a[2]=3 으로 만들라는 것과 같으며 위의 코드들의 줄임말이다. 문제는 a[3]이라는 공간은 없는데 거기다가 숫자 0을 집어넣으라고 하니 오류가 난다. 실행해보면 컴파일은 되고 작동은 하지 않으며 이런 메세지가 뜬다.

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at Test27.main(Test27.java:7)

메인메소드의 7번째줄에서 java.lang 패키지의 Exception 클래스에 관련된ArrayIndexOutOfBoundsException 오류(철자 되게 길구먼 -_*)가 나는걸 볼수 있다. 코딩상의 문제이므로 간단하게 이 코드 빼버리면 되지만 우리는 예외처리 공부를 해야하니까 try catch 블록을 이용해 이런 오류를 극복(?)시키는 방법을 알아보겠다. 기대하시라~ 쨔쨘...ㅎㅎ



위의 예제를 실행하면 아래와 같은 결과를 얻게 된다.

java.lang.ArrayIndexOutOfBoundsException: 3
6

오류가 나는 부분을 try 블록을 감싸고 아까 위에서 나온 오류를 catch문을 통해 받아서 관련 예외이름을 출력하라고 명령을 주었다. 6이라는 숫자를 보니 프로그램이 제대로 작동했다는 것을 알수 있다. 우리는 배열요소들을 전부 합하라는 명령을 내렸으니 1+2+3은 6이 된다. 이제 try catch 블록을 이용해 예외처리를 하는 방법에 대해서 어느 정도 이해했으리라 본다.

이제와서 하는 얘기지만 사실 catch문에 수식을 저렇게 명확하게 오류명을 적을 필요가 없다. 저 긴 영어를 언제 다 치냐? ㅎㅎ 이런 오류들은 Exception 클래스를 계승(?)받은 것이다. 따라서 맨 위의 대장 클래스인 Exception만 그냥 써줘도 어떤 예외든지 처리된다.^^ catch (Exception e) 이런 식으로만 써도 된다. 한번 실행해 보기 바란다. 되는지 안되는지... ㅎㅎ 늦게 알려줘서 필자를 탓하는 이가 있을지 모르겠지만 우리는 공부하는 입장에서 정석을 제대로 알아야 하지 않겠는가? *.^

또한 메소드내에서 오류가 날 경우가 있는데 이럴때는 메소드도 예외처리하면 된다. 메소드 옆에 throws 키워드를 이용해 예외를 다른곳으로 보내서 처리하는 방법이 있다. 예전 입출력 시간에 필자가 언급한바 있다. 그래도 다시 한번 간략히 설명하자면

결과값 ??ex( ) throws ???Exception
{
//예외가 발생하는 부분
}

위와 같이 throws를 이용해 예외처리를 하면 이 메소드 ??ex( )를 쓰기 위해 다른 곳에서 실행하는 곳이 있을 것이다. 어디선가 이렇게 아래와 같이 메소드를 실행하는 곳이 있을텐데 바로 그곳을 try 블록으로 감싸고 catch 블록을 써서 예외처리를 아까처럼 하면 된다.

try
{
??ex( );
}
catch (???Exception e)
{
...
}

기본에 충실하면 이런 정도의 응용은 어렵지 않을 것이다. 이 밖에 Exception 클래스를 본인이 직접 상속받고 클래스 생성자에 따로 예외오류를 규정하고 사용하는 방법도 있다. 이런 방식은 오류가 나는 부분 메소드에 아까와 같이 throws로 오류 부분을 쓰고 다른 곳이 아닌 바로 그 메소드 안의 명령문에서 throw new라는 키워드를 써주고 임의로 만든 오류 클래스를 객체 생성하면 예외처리가 된다. 아직 클래스 상속이라는 것을 배우지 않았으므로 그런게 있다라고만 알아두고 나중에 개념을 확립한후에 컴백해서 다시 읽어보면 모든게 이해가 될 것이니 아까했던 try catch 구문이나 확실하게 알아두도록 하자. 뒤에 언급한 throws 예외처리 부분은 try catch 구문에 비하면 이미 저번에 한번 해봤기도 하고 비교적 쉬운 편이므로 그리 염려할 필요(?)가 없을 것이다.^^

댓글 없음:

댓글 쓰기