[Java] 자바 #29, 예외처리(Exception, try-catch문) 및 예외 종류 예제 및 응용

예외, Exception


 - 컴파일 발견 X 런타임발견 O

 - 실행중 발생하는 에러

 - 개발자가 예측을 할수도 없을수도 있다. -> 예측을 하더라도 발생할 수 있는 에러.

 - 주로 발생하는 경우 : 프로그램 외부와의 소통을 하는 업무(파일 입출력, DB입출력, 네트워크 입출력 등...)



예외처리, Exception Handling

 1. 전통적인 방식. (*조건문*)

 2. 특화된 구문. (**try-catch(finally)문**)


전통적인 방식( 하드코딩의 하드코딩의 하드코딩 )


사용자로부터 숫자1개 입력받기. > 업무진행.

int num = 0;


// 0이 아닐때만 일을 한다.

if (num != 0) { 

// 업무 코드, *비즈니스코드*

System.out.printf("100 / %d = %d\n", num, 100 / num);

} else {

System.out.printf("0을 입력하면 안됩니다.\n");

}

//java.lang.ArithmeticException 0으로 나눈 예외

System.out.printf("100 / %d = %d\n",num,100/num);


>> 0 을 입력하면 에러가 발생한다는 상황을 개발자가 미리 인지하고 있어야 한다. 하지만 개발자는 모든 예외상황을 예측할 수 없으므로 아주 좋지 않은 방법이다.


특화된 구문을 이용한 방식( try ~ catch 구문)


// 사용자로부터 숫자1개 입력받기. > 업무진행.

int num = 0;


try {

System.out.println("테스트입니다.");

System.out.printf("100 / %d = %d\n", num, 100 / num);

System.out.println("테스트입니다.");

} catch (Exception e) { // 가인자값.

System.out.printf("0을 입력하면 안됩니다.\n");

// 예외처리 코드.

System.out.println(e.getMessage());

System.out.println(e.toString());

System.out.println(e.getStackTrace()); 

  - 위 3개는 에러메시지 출력하게 해줌. 각각 다르니 꼭 출력해보세요.

}


예외 종류


1. java.lang.ArithmeticException : 0으로 나눈 예외

>> 전통적인 예외처리에 있는 코드처럼 100/0 처럼 분모에 0이 있을 때 발생하는 예외이다. 계산과정을 사용하지 않는 한 잘 나타나지는 않는다.


2. java.lang.ArrayIndexOutOfBoundsException

>> 배열의 인덱스로 배열의 요소를 접근하려고 할때 [ ] 안에 알맞은 값을 넣지 않은 경우에 나타난다. 예를들어 0보다 작은 값을 배열의 [ ] 안에 넣거나 배열의 length-1(가장 마지막 배열의 위치는 항상)보다 큰 값을 넣었을 때 나타난다.


3. java.lang.NullPointerException

>> 변수에는 아직 객체생성이 일어나지 않았는데 해당 객체를 호출하여 객체에 있는 메소드를 호출한다거나 할 때 발생. 아래의 예제에서는 Random 객체에 new 키워드를 사용하여 객체 생성을 하지 안았기 때문에 변수안에 아무것도 없는데(null) nextInt 메소드를 사용하려고 하였기 때문에 발생.


4. java.lang.ClassCastException

>>타입변환을 할 수 없는 타입으로 형변환을 진행하려고 할 때 발생한다. 


ex) 2, 3, 4 예제

// 배열 > index 처리 > 예외 발생

int[] nums = { 10, 20, 30 };


java.lang.ArrayIndexOutOfBoundsException

try {

nums[3] = 40;

System.out.println(nums[3]);

} catch (Exception e) {

System.out.println("배열 첨자 오류");

}


java.lang.NullPointerException

try {

Random ran = null;

System.out.println(ran.nextInt(10));

} catch (Exception e) {

System.out.println("랜덤 객체 없음");

}

java.lang.ClassCastException

try {

  객체는 없지만 느낌만 살펴보세요.

Printer[] list = new Printer[2];

list[0] = new LG300();

list[1] = new HP400();


((LG300) list[1]).call();

} catch (Exception e) {

System.out.println("클래스 캐스팅 에러");

}  


5. 예상 못한 예외는 Exception으로 흐른다.



try {

// 업무 1.

  int num = 0;

System.out.printf("100 / %d = %d\n", num, 100 / num);


// 업무 2.

int[] nums = { 10, 20, 30 };

System.out.println(nums[2]);


// 업무 3.

Random ran = new Random();

System.out.println(ran.nextInt(10));


} catch (ArrayIndexOutOfBoundsException e) {

System.out.println("배열 인덱스 범위 초과");

} catch (ArithmeticException e) {

System.out.println("0으로 나눔");

} catch (NullPointerException e) {

System.out.println("널 객체 참조.");

} catch (Exception e) {

System.out.println("다른 오류 발생.");  위의 업무 3개는 각각 catch절에 예외처리를 했지만, 간혹 예기치 못한 예외가 발생하는 경우가 있다. 그러할 때를 대비하여 전체 Exception을 예외처리 해주어야한다.

}


의문점? : 그렇다면 그냥 애초에 Exception만 catch절에 해놓으면 되는거 아닌가요??

>> 그래도 되는 경우는 그래도 좋다. 하지만 프로그램을 개발할 때 예외가 발생하는 상황마다 특정한 방식으로 예외를 처리해주어야 하는 경우가 있다. 각각의 해결방안이 다르다는 것을 인지해야 한다. 이건 개발을 많이 해보다보면 자연스럽게 알게 될것이다.



예외 발생시키기 & 예외 미루기


개발자가 강제로 예외를 발생시킴 > 예외 발생시키기

// throw new Exception("3의 배수가 아닙니다"); //반드시 조건부로 한다.

throw new Exception("A001"); // 각종 예외상황을 미리 설정하고 , 조사를해놓고 넘버링을 한것. 표준화


"A001" 같은 코드는 비즈니스적인 프로그래밍을 할때 예외상황을 미리 파악하여 코드화해놓은 것이고 다른 사람이 에러를 봣을 때 어떤 에러유형인지 파악하기 쉽게 정리해놓은 문서에 코드를 써서 관리하는 상황을 나타낸 것.


예외 미루기

상황 : 어떤 회사는 제주, 광주, 부산의 지사가 있다. 본점은 서울이라고 할때 어떤 문제가 생기면 본사로 문제상황을 넘겨주어야 하는데 이러한 상황을 자바코드로 예를 들면 다음과 같다.


private static void 본사()  {

try {

부산지사();

광주지사();

제주지사();

} catch (Exception e) { 

    예외처리 코드();  

}

}

private static void 제주지사() throws Exception {

int n = 0;

System.out.println(100 / n); 에러

}


private static void 광주지사() throws Exception {

Random ran = null;

System.out.println(ran.nextInt(10)); 에러

}


private static void 부산지사() throws Exception {

int[] nums = { 10, 20, 30 };

System.out.println(nums[3]); 에러

}


>> 예제설명 : 본사() 메소드에서 제주지사(), 광주지사(), 부산지사() 메소드를 호출하였다. 각각의 지사메소드에서 예외가 발생할 경우 예외 처리를 해주어야하는데 바로 처리하지 않고 예외를 발생시킨 코드를 호출한 곳으로 그 예외를 넘겨버린다. 즉, 지사에게 일을 시킨것은 본사이므로 이를 책임질 본사메소드로 예외를 넘겨서 본사에서 예외를 처리하여 준다!!


댓글

Designed by JB FACTORY