본문 바로가기

플밍 is 뭔들/JAVA

[자바] 예외처리 (Exception)

※ 에러의 종류

 - 컴파일 에러 : 컴파일 도중에 생기는 에러 (소스코드에 대한 오타, 잘못된 구문, 자료형 체크 등등)

 - 런타임 에러 : 실행 도중 생기는 에러 (컴파일 완료 후 시스템 실행시 생기는 에러)


※ 자바에서 예외처리
자바에서는 실행 시 발생할 수 있는 오류를 에러와 예외 두가지로 구분한다.

  • 에러 - 메모리부족, 스택오버플로우등 발생하면 복구할 수 없는 심각한 오류
  • 예외 - 발생하더라도 수습이 될 수 있는 비교적 덜 심각한 것

에러가 발생하면 프로그램의 비정상적인 종료를 막을 순 없지만 예외가 발생하면 프로그래머가 적잘한 코드를 미리 작성해 놓으면 프로그램의 비정상적인 종료를 막을 수 있다.


※ 예외처리의 정의와 목적
  • 정의 - 프로그램 실행 시 발생할 수 있는 예외의 발생에 대비한 코드를 작성
  • 목적 - 프로그램의 비정상 적인 종료를 막고 정상적인 실행 상태를 유지하는 것


※ try-catch
 예외를 처리하는 구문
ex)

try{
    //예외가 발생할 가능성이 있는 코드를 넣는다.    
}catch(Exception1 e1){
    //Exception1이 발생했을 때, 처리하는 코드를 작성
}catch(Exception2 e2){
    //Exception2가 발생했을 때, 처리하는 코드를 작성.
    ...
}catch(ExceptionN eN){
    //ExeeptionN이 발생했을 때, 처리하는 코드를 작성.
}



※ try-catch문의 흐름

    - try블럭 내에서 예외가 발생한 경우
  1. 발생한 예외와 일치하는 예외가 있는지 catch블럭에서 확인
  2. 일치하는 catch를 발견 하면 catch안의 문장을 수행하고 try블럭 내에 예외가 발생된 부분 다음 코드가 있던 없던 전체 try-catch문을 빠져나온 후 그 다음 문장을 계속해서 수행한다. 만일 일치하는 catch블럭을 찾지 못한 경우 예외처리는 안된다.
    - try블럭 내에서 예외가 발생하지 않은 경우

  1. catch블럭을 거치지 않고 try-catch문을 빠져나와 수행을 계속한다. 


※ 예외 발생시키기
프로그래머가 고의로 예외를 발생시킬 수 있다. 방법은 아래와 같다.
ex)
1.예외 클래스의 객체를 생성한다.
Exception e = new Exception("고의적으로 예외를 발생시킴");

2.키워드 throw를 이용해 예외를 발생시킨다.
throw e;


public static void main(String[] args) {
           
    try {
        Exception e = new Exception("고의예외");
         throw e;
    }catch (Exception e) {
        System.out.println(e.getMessage());
    }
}



※ finally 블럭
try-catch문과 함께 예외의 발생 여부와 상관없이 마지막에 무조건 실행되어야할 코드를 포함 시킬 목적으로 사용된다.
public static void main(String[] args) {
           
    try {
        Exception e = new Exception("고의예외");
        throw e;
    }catch (Exception e) {
        System.out.println(e.getMessage());
    }finally {
        System.out.println("try-catch의 마지막에 무조건 실행된답니다.");
    }
}


※ 메서드에 예외 처리 선언하기
예외 처리 방법은 try-catch문을 사용하는 것 이외에, 예외를 메서드에 선언하는 방법이 있다.

public void method() throws Exception1, Exception2, ... , ExceptionN {//메서드 내용}

예외를 메서드에 선언했을 때 오는 효과는 무엇이 있을까?

  1. 예외를 메서드에 선언함으로써 메서드를 사용하려는 사람이 메서드의 선언부를 보고 처리해야할 예외가 무엇인지 알 수 있다.
  1. 예외처리 구간을 분담할 수 있다.
          - 사실 메서드에 예외를 선언하는 것은 이러한 예외가 발생시 나를 호출한 곳으로 예외를 넘기겠다는 것이다.
            소스코드 내에 자체적으로 처리해도 되는것은 try-catch를 사용하면 되지만 그렇지 못한 것들 예를들어 
            메서드의 리턴값을 처리할 때 예외가 발생할 상황이라면 리턴값을 받는 부분에서 예외를 받아 처리해야한다.
            그리고 예외처리를 잘 사용하면 소스가 깔끔해 질 수 있다. 예외처리를 한다고 try-catch를 떡칠하는 것 보단
            필요한곳에 적제적소로 사용해야 한다.

ex)

public static void main(String[] args){
    
    ...     
    
    try{
        File f = createFile(fileName);
        System.out.println(f.getName()+"파일처리가 성공적으로 되었습니다.");    

    }catch(Exception e){
        System.out.println("파일생성 함수의 리턴값이 올바르지 않습니다.");
        e.getMessage();
    }    

}


public static File createFile(String fileName) throws Exception {
    
    if(fileName == null || fileName.equals("")){
        //파일 이름이 올바르지 않을 때 예외를 넘김
        throw new Exception("파일이름이 유효하지 않습니다.");
    }
        
    //파일 생성 과정 구현
    
    return f; //f는 파일객체   
}


※ 예외 되던지기 (Exception re-throwing)
try-catch문을 통해 메서드 내에서 예외를 처리하고, 그 나머지는 선언부에 지정하여 호출한 메서드에서 처리하도록 함으로써, 양쪽에서 나눠서 처리할 수 있다. 또한 단 하나의 예외에 대해서도 예외가 발생한 메서드와 호출한 메서드, 양쪽에서 처리가 가능하다.
그렇기 때문에 위의 두 상황에 맞게 응용하여 사용하면 된다. 
아래는 예외를 되던지기하는 기본 형태이다. catch 부분에서 다시한번 e를 throw 하고있다.

public static void main(String[] args) {
           
    try {
        method();
    }catch (Exception e) {
        System.out.println("메인메서드 예외처리");
    }
}

public static void method() throws Exception {
           
    try {
        throw new Exception("고의예외");
    }catch (Exception e) {
        System.out.println(e.getMessage());
        throw e;
    }
}


※ 사용자정의 예외 만들기
기존의 정의된 예외 클래스 외에 필요에 따라 프로그래머가 새로운 예외 클래스를 정의하여 사용할 수 있다. 보통 Exception클래스를 상속받아 제작하지만 필요에 따라 알맞은 예외클래스를 선택하면 된다.

public class MyException extends Exception{
      
      private final int ERR_CODE;
      
      public MyException(String msg, int errCode) {
            super(msg);
            ERR_CODE= errCode;
      }
      public MyException(String msg) {
            this(msg, 100);
      }
      
      public int getErrCode(){
            return ERR_CODE;
      }
}