JAVA

[JAVA] 예외처리: try-catch문, finally문

정공자씨 2024. 4. 24. 14:24

 

 

에러(Error)
자바 프로그램 실행 시에 의도하지 않게 발생하는 문제점

[ 자바 에러의 종류 ]
1. 에러
  - 프로그램의 중요한 기능의 수행을 불가능하게 하는 에러
  - 에러를 해결한 후, 프로그램을 재실행해야 함

2. 예외
  - 에러보다 가벼운 문제
  - 프로그램 자체적으로 문제 해결이 가능

 

 

예외 처리를 한다는 것

자바 프로그램 실행 중에 예외가 발생하더라도, 비정상 종료되는 것을 방지

 

 

예외를 처리하지 않고 실행하는 경우

public class Test {
    public static void main(String[] args) {
        int [] numbers = new int[2];
        
        numbers[0] = 0;
        numbers[1] = 1;
        numbers[2] = 2; //index의 범위를 넘어버리는 에러가 발생
                        //컴파일러(저장시)에 오류를 알려주지 않음

        System.out.println("프로그램 종료");
    }
}

 

[ 실행결과 ]

  • 배열 크기를 2개로 정해놨는데
  • 배열의 범위를 벗어난 인덱스인 number[2]에 값을 대입해서 에러가 발생함
  • println() 메서드는 발생한 예외와 상관이 없는 구문이지만, println("프로그램 종료")를 출력하지 않고 비정상 종료
    • 즉, 실행 중에 예외가 발생하면
    • 예외와 상관 없는 부분도 영향을 받아서 프로그램이 비정상적으로 종료가 됨
[ 예외 처리를 해주지 않으면 ]
예외 발생 시에 예외와 관련없는 기능도 비정상적으로 종료 될 수 있음

[ 이 때에 try/catch문으로 예외 처리를 하면 ]
실행 중에 예외가 발생하더라도 프로그램이 정상종료 될 수 있음

 

 

 

 

 

try/catch문으로 예외 처리

try 블록 

  • 예외가 발생할 수 있는 코드를 작성

 

catch문

  • 실행 시에 try 블록 코드에서 예외가 발생하면, JVM에게 예외를 던지고
  • 발생한 예외를 JVM이 분석한 후에, 해당하는 예외 클래스의 인스턴스를 생성함
  • JVM이 생성한 예외 객체를 catch문으로 다시 던짐
  • catch문의 매개변수가 예외 객체를 받아서 catch 구문에서 예외를 처리

 

try/catch문으로 예외를 처리하기

public class Test {
    public static void main(String[] args) {		
        int [] numbers = new int[2];

        try {
            numbers[0] = 0;
            numbers[1] = 1;
            numbers[2] = 2; // 예외가 발생하면, JVM이 받아서
                            // ArrayIndexOutOfBoundsException 객체를 생성한 후에, catch문으로 던짐
        } catch(ArrayIndexOutOfBoundsException e) {
            // 생성된 예외 객체를 매개변수 e가 받아서 예외처리를 함
            System.out.println("예외를 처리하였습니다.");
        }
        // 예외처리 후, 다음의 메시지 출력문을 정상적으로 실행하고 종료함
        System.out.println("프로그램 종료");
        System.out.println(Arrays.toString(numbers)); // [0,1]
    }
}

 

[ 실행 결과 ]

 

numers[2] = 2;    // 예외 발생 코드
  • 위 코드에서 배열의 범위를 벗어나(3개) 값을 초기화 하려고 해서 에러가 발생하고
    • JVM이 그 예외를 받아 예외 객체를 생성한 후에 catch문으로 던지고
    • 생성된 예외 객체를 매개변수 e가 받아서, catch문에서 예외 처리를 함
  • 예외 처리를 하였기 때문에, catch문 이후의 출력문이 출력됨
  • 예외를 처리한 후에는 정상적으로 catch문 바깥의 코드들이 정상 실행됨

 

 

 

try - catch - finally문

정의

  • 예외가 발생하든, 발생하지 않든 반드시 실행해야 하는 기능에 사용
  • 어떤 예외가 발생 하더하도 반드시 실행해야 하는 부분이 있다면 finally문으로 처리

 

용도

  • 주로 입출력 장치 등의 외부 장치를 연동하여 사용 후에 마무리 시에 사용

 

try - catch - finally 실행 순서

  1. 예외가 발생한 경우 : try →  catch  →   finally
  2. 예외가 발생하지 않은 경우 : try  →   finally

 

반드시 실행해야 하는 메서드가 있는데 에러 발생하는 경우

1.  finally문에 없는 경우

trycatch.notExeute()  메서드를 반드시 실행해야 하는 경우
  • trycatch.printAdd(); 메서드에서 오류가 나면, catch문에서 예외를 처기하기 때문에
  • 그 아래 코드인 trycatch.notExeute(); 가 실행되지 않음 
public class Main {
    public static void main(String[] args) {
        Try trycatch = new Try();

        try {
            trycatch.add(100);
            trycatch.printAdd();  // 이 메서드 실행 중에 에러가 나면 catch문으로 넘어가기 때문에
            trycatch.notExeute();  // 이 코드는 실행되지 않음    
        } catch (FileNotFoundException e) {
            // 예외 처리 1
        } catch (IOException e) {
            // 예외 처리 2
        } catch (Exception e) {
            // 예외 처리 3
        }
    }
}

 

 

2. finally문에 있는 경우

trycatch.exeute() 메서드를 반드시 실행해야 하는 경우
  • trycatch.printAdd(); 메서드에서 오류가 나면, catch문에서 예외 처리를 하고
  • 에러의 유무와 상관 없이 실행해야 하는 finally문이 있기 때문에
    • trycatch.exeute() 메서드를 실행하기 때문에 출력이 됨
public class Main {
    public static void main(String[] args) {
        Try trycatch = new Try();

        try {
            trycatch.add(100);
            trycatch.printAdd();  // 이 메서드 실행 중에 FileNotFoundException 에러가 발생하면

        } catch (FileNotFoundException e) { // 해당 catch문에서 예외(에러)를 처리하고
            // 예외 처리 1
        } catch (IOException e) {
            // 예외 처리 2
        } catch (Exception e) {
            // 예외 처리 3
        } 

        finally {   // 에러가 나든 나지 않든 무조건 실행
            trycatch.exeute();  
        }
    }
}

 

예제

public class Test {
    public static void main(String[] args) {		
        int [] numbers = new int[2];

        try {
            numbers[0] = 0;
            numbers[1] = 1;
            numbers[2] = 2; // ArrayIndexOutOfBoundsException

            // numbers[1] = 3/0;  // ArithmeticException
        } catch(ArrayIndexOutOfBoundsException e) {
            System.out.println("배열의 범위를 벗어났습니다");
        } catch(ArithmeticException e) {
            System.out.println("0으로 나눌 수 없습니다");
        } 
        finally { // 예외의 발생과 상관 없이 항상 실행
            System.out.println("finally 블록은 항상 실행됩니다");
        }
    }
}

 

[ 실행 결과 ] 

 

 

 

 

 

 

 

상위의 예외클래스(Exception)

  • Exception이 가장 상위의 예외 클래스
public class ex18 {

    public static void main(String[] args) {		
        try {
             // ArithmeticException 예외 발생
             // ArrayIndexOutOfBoundsException 예외 발생
        } catch(Exception e) {
             // 모든 예외 클래스를 받을 수 있는 Exception
        }
    }
}