예외처리(exception handling)

boom.jun.cho·2022년 5월 17일
0

1.예외처리

1.1 프로그램오류

  • 컴파일 에러 : 컴파일 시에 발생하는 에러
  • 런타임 에러 : 실행 시에 발생하는 에러
  • 논리적 에러 : 실행은 되지만, 의도와 다르게 동작하는 것

자바에서는 실행 시 발생할 수 있는 프로그램 오류를 '에러(error)'와 예외(exception)', 두가지로 구분한다.

에러는 메모리 부족(OutOfMemomryError)이나 스택오버플로우(StackOverflowError)와 같이 일단 발생하면 복구할 수 없는 심각한 오류이고, 예외는 발생하더라도 수습될 수 있는 비교적 덜 심각한 에러이다.

  • 에러 : 프로그램 코드에 의해서 수습될 수 없는 심각한 오류
  • 예외 : 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류

1.2 예외 클래스의 계층 구조

  • Exception클래스들 : 사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외
  • RuntimeExeption클래스들 : 프로그래머의 실수로 발생하는 예외

1.3 예외처리하기 -try-catch문

class ExceptionEx3 {
	public static void main(String args[]) {
    	int number = 100;
        int result = 0;
        
        for(int i = 0; i < 10; i++) {
        	try {
            	result = number / (int)(Math.random() * 10);
                System.out.println(result);
            } catch(ArithmeticException e) {
            	System.out.println("0");
            } 
        }
    }
}
        

1.4 try-catch문에서의 흐름

  • try블럭 내에서 예외가 발생한 경우,
    1 .발생한 예외와 일치하는 catch블럭이 있는지 확인한다.
    2 .일치하는 catch블록을 찾게 되면, 그 catch블록 내의 문장들을 수행하고 전체 try-catch문을 빠져나가서 그 다음 문장을 계속해서 수행한다. 만일 일치하는 catch블럭을 찾지 못하면, 예외는 처리되지 못한다.

  • try블럭 내에서 예외가 발생하지 않은 경우,
    1 .catch블럭을 거치지 않고 전체 try-catch문을 빠져나가서 수행을 계속한다.

1.5 예외의 발생과 catch블럭

catch블럭은 괄호()와 블럭{} 두 부분으로 나눠져 있는데, 괄호()내에는 처리하고자 하는 예외와 같은 타입의 참조변수 하나를 선언해야 한다.
예외가 발생하면, 발생한 예외에 해당하는 클래스의 인스턴스가 만들어진다.

예외가 발생했을 때 생성되는 예외 클래스의 인스턴스에는 발생한 예외에 대한 정보가 담겨 있으며,
getMessage()와 printStackTrace()을 통해서 이 정보들을 얻을 수 있다.
catch블럭의 괄호()에 선언된 참조변수를 통해 이 인스턴스에 접근할 수 있다. 이 참조 변수는 선언된
catch블럭 내에서만 사용 가능하며, 자주 사용되는 메서드는 다음과 같다.

  • printStackTrace() : 예외발생 당시의 호출스택(Call Stack)에 있었던 메서드의 정보와 예외 메시지를 화면에 출력한다.
  • getMessage() : 발생한 예외클래스의 인스턴스에 저장된 메시지를 얻을 수 있다.

1.6 예외 발생시키기

키워드 throw를 사용해서 프로그래머가 고의로 예외를 발생시킬 수 있으며, 방법은 아래의 순서를 따르면 된다.

  • 1.먼저, 연산자 new를 이용해서 발생시키려는 예외 클래스의 객체를 만든 다음
    Exception e = new Exception("고의로 발생시켰음");
  • 2.키워드 throw를 이용해서 예외를 발생시킨다.
    throw e;

1.7 메서드에 예외 선언하기

메서드에 예외를 선언하려면, 메서드의 선언부에 키워드 throws를 사용해서 메서드 내에서 발생할 수 있는 예외를 적어주기만 하면 된다. 그리고 예외가 여러 개일 경우에는 쉼표(,)로 구분한다.

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

예외가 발생한 메서드에서 예외처리를 하지 않고 자신을 호출한 메서드에게 예외를 넘겨줄 수는 있지만,
이것으로 예외가 처리된 것은 아니고 예외를 단순히 전달만 하는 것이다. 결국 어느 한 곳에서는 반드시 try-catch문으로 예외처리를 해주어야 한다.

1.8 finally블럭

finally블럭은 예외의 발생여부에 상관없이 실행되어야할 코드를 포함시킬 목적으로 사용된다.
try-catch문의 끝에 선택적으로 덧붙여 사용할 수 있으며, try-catch-finally의 순서로 구성된다.

1.9 자동 자원 반환 -try-with-resource문

이 구문은 주로 입출력(I/O)과 관련된 클래스를 사용할 때 유용하다.

  • void addSuppressed(Throwable exception) 억제된 예외를 추가
    Throwable[] getSuppressed() 억제된 예외(배열)를 반환

1.10 사용자정의 예외 만들기

Exception클래스 또는 RunrimeException 클래스로부터 상속받아 클래스를 만들지만, 필요에 따라서 알맞은 에외 클래스를 선택할 수 있다. 필요에 따라 예외처리의 여부를 선택할 수 있는 'unchecked예외'가 강제적인 'checked예외'보다 더 환영받고 있다.

1.11 예외 되던지기(exception re-throwing)

한 메서드에서 발생할 수 있는 예외가 여럿인 경우, 몇 개는 try-catch문을 통해서 메서드 내에서 자체적으로 처리하고, 그 나머지는 선언부에 지정하여 호출한 메서드에서 처리하도록 함으로써, 양쪽에서 나눠서 처리되도록 할 수 있다. 심지어는 단 하나의 예외에 대해서도 예외가 발생한 메서드와 호출한 메서드, 양족에서 처히하도록 할 수 있다.

이 방법은 하나의 예외에 대해서 예외가 발생한 메서드와 이를 호출한 메서드 양쪽 모두에서 처리해줘야 할 작업이 있을 때 사용된다. 이때 주의점은 예외가 발생할 메서드에서는 try-catch문을 사용해서 예외처리를 해줌과 동시에 메서드의 선언부에 발생할 예외를 throw에 지정해줘야 한다는 것이다.

1.12 연결된 예외(chained exception)

한 예외가 다른 예외를 발생시킬 수도 있다. 예를 들어 예외 A가 예외 B를 발생시켰다면, A를 B의 '원인 예외(cause exception)'라고 한다. initCause()는 Exception클래스의 조상인 Throwable클래스에 정의되어 있기 때문에 모든 예외에서 사용 가능하다.

  • Throwable initCause (Throwable cause) 지정한 예외를 원인 예외로 등록
  • Throwable getCause() 원인 예외를 반환

여러가지 예외를 하나의 큰 분류의 예외로 묶어서 다루기 위해, 또 다른 이유는 checked예외를 unchecked예외로 바꿀 수 있도록 하기 위해서이다. 예외처리를 선택적으로 할 수 있기 때문이다.

profile
하루하루 최선을

0개의 댓글