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

예외처리

by 신일석 2019. 5. 26.

예외처리

예외처리(Exception)

자바 프로그램이 실행중에 오류를 만났을때 이를 처리하는 것
예외란 자바 프로그램이 실행 도중 실행을 중단할 정도의 오류는 아니지만 비정상적으로 동작하는 것을 말한다.
자바 프로그램은 예외가 발생했을때 처리하지 않으면 예외에 대한 정보를 화면에 출력하고 실행을 종료한다.

<클래스 계층구조>

Error 클래스 Exception 클래스
시스템 구조상의 문제로 발생하는 심각한 오류 프로그램의 알고리즘이나 실행 절차상의 문제로 발생하는 경미한 오류

Exception 클래스는 Throwable 클래스가 제공하는 toString(), printStackTrace() 메소드를 상속받는다.
toString() 예외 객체를 String 형으로 변환
printStackTrace() 예외가 발생한 위치를 상세하게 화면에 출력

예외의 종류에 따른 구분

checked Exception과 unchecked Exception이 있다.

checked Exception(1)

소스코드가 예외처리를 반드시 포함해야 하는 예외로 컴파일러가 예외처리 구분을 포함하는지 확인(checked)하고 없으면 컴파일 에러가 발생한다.
Runtime Exception의 서브 클래스로 분류되는 예외를 제외한 모든 예외가 여기에 해당한다.
예를 들면 입출력과 관련된 IOException 예외가 있다.

unchecked Exception(1)

매우 자주 발생하는 예외들로 숫자를 0으로 나누거나 범위를 벗어나는 배열의 첨자를 참조하고 null 객체의 메소드를 호출하는 경우 등이 있다.
컴파일러가 예외처리 구문을 확인하지 않으며(unchecked) Runtime Exception의 서브 클래스로 분류되는 예외가 해당된다.

예외처리 방법

예외처리 구문

구문

try {
    //예외가 발생할 수 있는 코드
} catch(발생하는 예외 선언) {
    //예외처리 구문
}

checked Exception(2)

예외처리 구문의 작성시 Java API 문서에 메소드를 설명하는 부분에 명시되어 있는 메소드가 발생시킬 수 있는 예외를 참고한다.

<예 FileWriter의 IOException>

FileWriter
public FileWriter(File file)
           throws IOException
Constructs a FileWriter object given a File object.
Parameters:
file - a File object to write to.
Throws:

IOException - if the file exists but is a directory rather than a regular file,
does not exist but cannot be created, or cannot be opened for any other reason

<클래스 계층>

java.lang.Object
    java.lang.Throwable
        java.lang.Exception
            java.io.IOException

<예 FileOutputStream의 예외처리>

import java.io.FileOutputStream;
import java.io.IOException;

public class ExceptionTest {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try {
            FileOutputStream output = new FileOutputStream("c:/out.txt");
            output.close();
        } catch (IOException e) {
            System.out.println(e.toString());
            e.printStackTrace();
        }
    }
}

예외가 한 개 이상인 경우 모든 예외는 Exception의 하위 클래스 이므로 Exception으로 처리도 가능하다.

unchecked Exception(2)

컴파일 오류가 발생하지 않는다. 실행 도중 비정상적으로 종료된다.
<예>

public class UnchkExceptionTest {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int[] a = new int[5];
        a[6] = 10;
    }
}

Java API 문서를 참고해 작성해 본다.

finally 블록

try-catch와 함께 사용되며 예외발생과 무관하게 항상 실행된다. 생략할 수 있다.
<예>


import java.io.FileOutputStream;
import java.io.IOException;

class FileOut {
    public void saveFile() {
        try {
            FileOutputStream output = new FileOutputStream("c:/out.txt");
            output.close();
        } catch (IOException e) {
            System.out.println(e.toString());
            e.printStackTrace();
        }
    }
}

public class ExceptionTest {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        FileOut fo = new FileOut();
        fo.saveFile();
    }
}

try-catch-finally 문에서 continue, break, return 등과 같은 분기문을 사용하는 것은 피하는 것이 좋다.
만약, try 블록이 분기문에 의해 종료되어야 한다면 finally블록을 실행한 후 분기문이 실행된다.

예외의 전파

일반적으로 예외는 예외가 발생한 곳에서 처리하지만 경우에 따라 다른 곳으로 전파시킬 수도 있다.

구문

throws <예외 이름>

위 예제를 발생한 곳으로 전파해 보겠습니다.
<예 예외의 전파>

import java.io.FileOutputStream;
import java.io.IOException;

class FileOut {
    public void saveFile() throws IOException {
        FileOutputStream output = new FileOutputStream("c:/out.txt");
        output.close();
    }
}

public class ExceptionTest {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try {
            FileOut fo = new FileOut();
            fo.saveFile();
        } catch (IOException e) {
            System.out.println(e.toString());
            e.printStackTrace();
        }
    }
}

사용자 정의 예외

사용자 정의 예외는 일반적으로 Exception의 서브 클래스로 정의하며, 슈퍼 클래스의 생성자를 호출하는 것이 일반적이다.
예외를 발생시킬때 'throw <예외 객체>' 구문을 사용하고, 예외를 전파하기 위해 throws <예외 이름>를 사용한다.

<예 사용자 예외>

class MyCalcEx extends Exception {
    private static final long serialVersionUID = 1L;
    public MyCalcEx() {
        super();
    }
    public String toString() {
        return "예외가 발했습니다.";
    }
}

class Calc {
    public int addNum(int x) throws MyCalcEx {
        if(x <= 0)
            throw new MyCalcEx();
        return x*x;
    }
}

public class UserException {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Calc mc = new Calc();
        try {
            System.out.println(mc.addNum(0));
        } catch(MyCalcEx e) {
            System.out.println(e);
        }
    }
}