[Java] 예외처리(try~catch, throws, throw)

JAVA 예외처리

예외처리
 목적 : 프로그램의 비정상 종료를 방지하고 정상상태를 유지할 수 있게 만든다. (견고한 프로그램)
 정의 : 사전에 예상되는 에러를 대비하는 코드를 만든다.

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

##예외처리(예외복구) try ~ catch 절

기본적인 예외처리 try ~ catch 사용방법

try {
//예외의 발생이 예상되는 로직(코드)

} catch (Exception e) { //인자로 예외클래스 인스턴스 즉 에러상황을 담고있는 객체를 전달
//에러 처리
//예외가 발생했을 때 실행되는 로직
} finally { //필수는 아니며 필요시에만 선언

               //정상처리하던 에러처리하던 무조건 실행해야되는것
               //예외여부와 관계없이 실행되는 로직
}

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

에러처리(확인)방법

e.getMessage() // 간단하게 에러 확인

e.toString() // 조금더 자세하게 에러확인

e.printStackTrace() // 아주 자세하게 에러확인 (몇번째줄에서 에러발생했는지 확인)



ex) 10을 0으로 나누어서 에러가 발생했을때

e.getMessage() // / by zero

e.toString() // java.lang.ArithmeticException: / by zero


e.printStackTrace() // java.lang.ArithmeticException: / by zero
                                        
at Access.divide(Access.java:16)
                                        at Access.main(Access.java:31)



* try에서 에러가 발생하여 catch절로 이동하여 에러를 처리하였다 하더라도 해당 메소드는 종료되지않고 try ~ catch문 밖에 작성된 코드들을 이어서 실행한다. 그러므로 finally를 사용해야한다. 


finally ==> 에러가 발생하든, 발생하지 않든 무조건 수행되는 문장
                  네트워크, 데이터베이스 프로그램에서는 반드시 존재
                   **서버를 연결 해제 
서버 연결 해제 ex) 데이터베이스는 접속을 정해진 만큼만 받을 수 있는데 특정 작업을 처리하다가 오류가 발생했을때  해당 데이터베이스와의 연결을 끊어주지않으면  계속해서 데이터베이스와의 연결이 유지되어 데이터베이스에 정해져있는 접속할수있는 범위를 넘어서 문제가 발생하게된다. 그러므로 finally를 사용하여 데이터베이스와의 연결을 직접 종료시켜줘야 한다.

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

##try ~ catch의 1) 전체 예외처리  2) 부분적 예외처리

1) 전체 예외처리 => 0,1,2 출력후 반복문 종료
          try
              {
                  for(int i = 0; i< 10; i++)
                      {
                          i == 3 error ===> i= 0, 1, 2
                      } ==> 종료
              } catch(Exception e){ }


2) 부분적 예외처리 => 0,1,2 출력후 에러부분 건너뛰고 반복문 계속 진행
           for(int i = 0; i< 10; i++)
           {
               try
               {
                   i == 3 error ===> i = 0, 1, 2 ==> 4 ~ 9
               } catch(Exception e){ } ==> i++ 이동
           }


for문 안에 try ~ catch는 에러를 제외하고 모두 실행 (continue 기능)
try ~ catch 문안에 for문은 에러 발생시 반복문 종료 (break 기능)

*** 만약 try 블럭안에 검사한 코드에서 오류가 없다면 해당 코드를 정상적으로 실행하고 예외처리 밖에 작성된 코드를 실행한다. 
반면에 에러가 발생하면 그 아래에 작성된 코드가 있더라도 에러가 발생하면 그 즉시 아래 코드를 건너뛰고 바로 catch블럭안에 코드를 실행하게된다.


ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

##다중예외처리 (예상되는 에러가 여러개 있는 경우)

try
{
    정상적으로 실행되는 문장
}
catch(예상되는 예외 클래스)   ==> 동일한 예외 클래스 오류발생
{
    예외처리
}
catch(예상되는 예외 클래스)
{
    예외처리
}
catch(예상되는 예외 클래스)
{
    예외처리
}

또는 


try
{
    정상적으로 실행되는 문장
}
catch(예상되는 예외 클래스1 | 예상되는 예외 클래스2 | 예상되는 예외 클래스3)  => 한곳에 몰아서도 가능 (or사용)
{
    예외처리
}


다중예외처리시 주의할점이있다.

예외처리 계층구조확인하고 작성하기

catch를 여러개 사용시에는 순서가 존재한다. 포괄적인 범위의 예외처리 이전에 세부적인 예외처리를 먼저 수행하여야한다. 예외처리를 한번할경우 보통 Exception를 사용하는데 그이유는 모든 예외를 포함하고 있는 예외이기 때문이다.

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

##예외처리 계층 구조


    최상위 클래스 => 모든 클래스의 상위 클래스
             Object
               l
          Throwable
               l
    ---------------------------------
    l                                    l
error                            Exception
                                        l
                        ---------------------------------
                        l                                     l
                  IOException            RuntimeException
                  ========                   ============
               CheckedException      unCheckedException 




ex)
public class MainClass2 {

public static void main(String[] args) {
// TODO Auto-generated method stub
try { 
} catch (ArithmeticException e) {
} catch (NumberFormatException e) {
} catch (ArrayIndexOutOfBoundsException e) {
} catch (Exception e) {
}
}
}


위 예제에서처럼 catch 안에 에러처리시 계층구조를 확인하고 세부적인것부터해서 큰범위로 작성해야지 에러가 발생하지 않는다. 다중예외처리시 계층구조를 지키지 않을경우 error 발생

IOException 과 RuntimeException을 모두 포함하고있는 Exception을 마지막에 작성해야 에러가 발생하지 않는다. Exception이 IOException과 RuntimeException를 포함하고 있는 큰범위

멀티 catch블럭 사용시 가장 마지막에 제일 큰 범위의 예외를 잡는다.


RuntimeException  exception throwable 을 마지막에 작성해줘서 예상치 못한 에러를 잡아야지 견고한 프로그램이 된다. 대표적으로 exception사용



부모에 RuntimeException이 없는 예외는
                Checked : 컴파일러가 예외처리했는지 확인 => 반드시 예외처리를 해야한다.
                    = 파일 입출력, 메모리 입출력, 네트워크 입출력
                    = 데이터베이스 연결
                    = 쓰레드 충돌

부모에  RuntimeException이 있는 예외는
                unChecked : 실행시 => 컴파일러가 예외처리를 확인하지 않는다.
                                예외처리 생략이 가능 => 필요한 경우에만 예외를 처리 할 수 있다.
                    = 사용자의 입력 ==> 문자열 => 정수변환
                                                 나누기 => 0을 입력


예외가 발생했을때 그 api의 사용자가 그 예외상황에서 프로그래머블하게 예외상황을 처리할 수 있다면 Checked Exception을 사용하는것이 바람직하며
어차피 사용자가 그것을 받아서 할 수 있는것이 없다 또는 그 상황에서 애플리케이션을 종료하는것이 최선이라고 생각되는 경우 unChecked Exception을 사용하는것이 바람직하다.

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

##예외처리(예외회피) throws

throws 사용단위는 메소드 단위이며 에러에 대한 예측이 가능하게 만든다. 대부분의 프로그램은 직접처리하며 throws 선언시 간접처리 한다.

대부분 호출하는곳에서 try ~ catch로 직접처리한다.

형식)
    메소드() trhows 예측한 예외 클래스 작성


throws을 작성할때는 계층구조를 확인하고 세부적인것부터해서 큰범위로 작성하던 try ~ catch와 달리 순서없이 나열이 가능하다. 

try ~ catch와 달리 throws로 예외처리를 다른 메소드에게 전가할때는 예외처리계층구조의 순서와 상관없이 작성이 가능하다.

pulbic void display() throws Exception, ArrayIndexOutOfBoundsException, NullPointerException    {

            }

 ==> display메서드를 호출한 메서드에서 throws로 전달된 Exception, ArrayIndexOutOfBoundsException, NullPointerException  세가지 예외처리를 모두 해야한다.


또는 메서옆에 전달할 예외를 작성하지 않고 예외를 가지고 그러니까 exception을 가지고 객체 인스턴스를 만들어 해당메서드를 호출한 메서드에서 해당 객체 인스턴스를 받아 오류를 처리하도록 할 수 도 있다.


ex)
public void divide(){
    if(...){
        throws new ArithmeticException("0으로 나눌 수 없습니다.");
    }
}
    

public static void main(String[] args){
       try{
            예외의 발생이 예상되는 로직
        } catch(ArithmeticException e) {
            e.getMessage(); //에러 발생시 0으로 나눌 수 없습니다. 출력
        }
}

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

##예외처리(예외전환) throw


원하는 예외처리를 수행하게 하는방법이다. 잘사용안한다. 주로 try ~ catch 또는 throws 사용

public class MainClass2 {

public static void main(String[] args) {

try {
int a = 10;
if (a%2 == 0) {
throw new ArithmeticException("로그인창으로 이동");
} else {
throw new Exception("회원가입창으로 이동");
}
} catch (ArithmeticException e) {
System.out.println(e.getMessage()); //짝수일경우 실행
} catch (NumberFormatException e) {
System.out.println(e.getMessage());
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e.getMessage());
} catch (Exception e) {
System.out.println(e.getMessage()); //홀수일경우 실행
}
}

}


ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

마지막으로 정리

자바의 모든 소스에는 예외처리가 있다. (생략 가능, 생략 불가능)
프로그램을 실행하는 과정에서 오작동, 비정상종료 => 에러/오류
        윈도우 : 쓰레드의 충돌, 주소값
        오작동, 비정상적으로 수행(프로그래머의 실수, 사용자의 오류(입력값, 작동을 잘못했을 경우))

에러의 종류
        컴파일 에러 : 컴파일시에 에러 (문법상의 에러)
        실행시 에러 : 실행시에 발생하는 에러 = 사용자 입력
        논리적 에러 : 실행이 되는데 동작을 다르게 ... ===> 프로그램의 순서가 틀린경우 => 저장, 입력 


실제 에러종류
        에러 : 프로그래머가 소스상에서 수정할 수 없는 에러
             = 메모리 부족현상
             = 이클립스 에러

         예외 : 가벼운 에러 (수정이 가능한 에러)
             = 소스상에서 수정이 가능
             = 사용자가 0을 입력했을 때 => 다시 입력시오
             = 아이디 중복체크
             = 파일 입출력 (경로명)
             = 서버 (IP)
             = ***오라클 (오라클 주소, SQL)



            예외처리 방법
                ***예외 복구 : 점프 => 프로그래머가 예외가 발생할 경우에 직접 처리 => 정상 상태 유지
                                try ~ catch ~ finally
                                ==> 직접 처리

                ***예외 회피 : 다른 메소드로 전송 => 시스템에 의해서 처리
                                throws
                                ==> 간접처리
                            
                예외 임의발생
                사용자 정의 예외 : 자바라이브러리에서 전체 에러를 지원하지 않는 경우
                ===========
                    => 데이터형 => 직접 데이터형 제작 (클래스)
                    => 메소드 => 사용자가 직접 제작
                    => 연산자, 제어문(X)



예외처리
    형식)
        1. 직접처리 (try ~ catch)
            try
            {
                실행이 가능한 코딩 (정상 수행할 수 있는 문장)
            } catch(예외클래스) {
                실행 과정에서 에러가 날 경우에 처리 문장
            }
            *** catch는 여러번 사용 가능
            *** finally를 사용할 수 있다 (필요한 경우에만 사용)
                서버, 데이터베이스 관련 => 서버닫기, 오라클 연결 해제

        2. 자바에서 제공하는 예외처리
             한개만 처리
                NumberFormatException
                ArrayIndexOutOfBoundsException
                NullPointerException
                IOException
                SQLException
             여러개 처리
                RuntimeException : 실행시 에러를 전체를 묶어서 한번에 처리
                Exception
                Throwable

        3. catch는 여러개를 사용할 수 있다.
            해당 에러를 찾는 경우에는 처음부터 마지막까지 검색 => 예외처리 순서대로 코딩

        4. try에서 에러가 발생하면 발생위치에서 catch로 이동
            ===================== 밑에 있는 소스는 실행되지 않는다.
            int a=10; ==> 실행
            int b=0; ==> 실행
            int c=a/b ==>에러발생 =====> catch로 이동
            System.out.println(c); ==> 실행되지 않는다.

        5. 목적 : 에러체크(에러 확인 ==> 소스 변경) ==> 디버깅

        6. 예외처리 => 수정이 가능한 에러

        7. 자바의 모든 코딩은 예외처리가 존재한다.
            단 실행시는 생략이 가능

        8. 예외처리는 반드시 처리해야하는 클래스가 존재
            ===============
                IO와 관련 *****
                쓰레드와 관련
                네트워크 관련 *****             ***** ==> web과 관련이 있다.
                데이터베이스 관련 ***** 

                    


try ~ catch 오류처리 순서존재

throws 오류처리 순서x

throws와 throw 차이점


3가지 종류의 예외처리를 알아보았고 찾아본바로 

1. try ~ catch
2. throws

두가지를 제일 많이 사용한다.



댓글