Java 예외처리Ⅰ

young-gue Park·2023년 2월 7일
0

Java

목록 보기
3/11
post-thumbnail

⚡ Java 예외처리 Ⅰ


📌 오류와 예외 클래스

🔷 오류란?

① 프로그램 코드 작성 중 실수로 발생하는 컴파일 오류(compile error)

  • 발생한 컴파일 오류를 모두 수정해야 프로그램이 정상 실행되기 때문에 이 오류는 원인을 알기 쉽다.

② 실행 중인 프로그램이 의도하지 않은 동작을 하거나 프로그램이 중지되는 실행 오류(runtime error)

  • 의도하지 않은 동작을 하는 경우를 버그(bug)라고 한다.
  • 이 경우는 예측하기 어렵고, 갑자기 프로그램이 멈춰버리기도 한다.

❗ 실제 서비스를 제공하던 중에 프로그램이 멈추면 서비스도 멈추기 때문에 굉장히 위험하다.

🤷‍♂️ 그럼 오류는 어떻게 막죠?

  • 로그(log) 분석을 통해 원인을 찾는다.

💡 로그(log)
소프트웨어 실행 중에 발생하는 여러 상황을 기록한 내용으로서 주로 파일에 기록한다.
이 파일을 로그 파일(log file)이라고 한다.

  • 또한 비정상종료를 막기 위해 자바에는 다양한 예외에 대한 처리 방법을 가지고 있다.

💡 예외(exception)
실행 오류는 자바 가상 머신에서 발생하는 시스템 오류(error)와 예외(exception)로 나뉜다. 시스템 오류와 달리 예외는 프로그램에서 제어할 수 있다.
ex) 읽어야할 파일이 없는 경우, 네트워크 연결이 안된 경우, 배열 요소가 없는 경우 등

🔷 예외 클래스

  • 자바에서 제공하는 오류에 대한 클래스들은 모두 Throwable 클래스에서 상속 받는다.
  • 이 중 시스템 오류를 담당하는 Error 클래스의 하위 클래스는 프로그램에서 제어하지 않는다.

🌟 그래서 우리는 프로그램에서 제어하는 부분인 Exception 클래스(예외 클래스)와 하위 클래스들을 익혀야 한다.

💡 예외 클래스 계층도
(⚠ 가장 사용 빈도가 높은 클래스들만 담았다.)

  • IOExcetion 클래스
    - 입출력에 대한 예외 처리
  • RuntimeException 클래스
    - 프로그램 실행 중 발생할 수 있는 오류에 대한 예외 처리
    - AruthmeticException 클래스: 산술 연산 중 발생할 수 있는 예외 처리 ex) 0으로 숫자 나누기
    - NullPointerException 클래스: 프로그램에 널값을 가지는 객체 참조를 사용할 때 발생하는 예외 처리

    💡 모든 참조 유형의 기본 값은 null이다. 그렇기 때문에 어떠한 값도 할당되지 않은 객체를 참조하려하면 예외가 발생한다.


📌 예외 처리하기

🔷 try-catch문

① try 블록에 예외가 발생할 가능성이 있는 코드를 작성한다.
② catch문의 괄호 안에 예외 상황에 따른 예외 타입을 작성한다.
③ catch 블록에 예외가 발생했을 때 수행될 코드를 작성한다.
④ try 블록 안에서 예외가 발생하면 catch 블록이 수행된다.

try {
	// 예외가 발생할 수 있는 코드
} catch(Exception e) {
	// try 블록 안에서 예외가 발생했을 때 예외를 처리하는 부분
}

🔷 try-catch문 응용하기

  • 배열에 저장하려는 값의 개수가 배열 범위를 벗어나면 발생하는 오류(ArrayIndexOutOfBounds Exception)처리

    TMI: 개인적으로 가장 많이 맞닥뜨렸던 오류였다... 😵‍💫

🖥 예외 처리가 되지 않은 코드

package GueJavaPackage1;

public class ArrayExceptionHandling {

	public static void main(String[] args) {
		int arr [] = new int[5];
		
		for(int i = 0; i <= 5; i++) {
			arr[i] = i;
			System.out.println(arr[i]);
		}
		System.out.println("종료!");
	}

}

배열의 범위를 벗어난 공간에 값을 저장하려하니 오류가 발생한다.
비정상 종료되어 뒤의 종료 문장을 수행하지 못한 모습이다.
이제 예외처리를 하자.

🖥 예외 처리한 코드

package GueJavaPackage1;

public class ArrayExceptionHandling {

	public static void main(String[] args) {
		int arr [] = new int[5];
		
		try {
			for(int i = 0; i <= 5; i++) {
				arr[i] = i;
				System.out.println(arr[i]);
			}
		} catch(ArrayIndexOutOfBoundsException e) {
			System.out.println(e);
			System.out.println("예외 처리하였습니다.");
		}
		System.out.println("종료!");
	}
}

예외 처리를 이용하여 프로그램의 비정상 종료를 막을 수 있었다.

💡 모든 예외 상황을 잡고 싶다면 Exception 타입을 Exception으로 작성하면 된다. 무슨 예외가 발생한건지 감도 못잡을 경우에만 사용하도록 하자. (물론 오류 이름이 항상 콘솔에 나타나기 때문에 모를 일은 거의 없을 것이다.)

💡 컴파일러에 의해 예외가 체크되는 경우가 있다. ex) 스트림 객체 이용 시
이러한 경우에는 컴파일러가 먼저 경고를 보내기 때문에 오류 확인 및 사전 예외 처리가 편하다.
(자세한 코드는 자바 입출력 파트에서 확인한다.)

🔷 try-catch-finally문

  • 비정상 종료든, 정상 종료든 반드시 실행되어야 하는 코드가 있다.

    ex) 끝 없이 계속 수행되는 웹 서비스에서 close() 메서드가 실행되지 않으면 리소스가 무한히 열리기만 하다 자원 문제가 발생한다.

  • 그렇기 때문에 try문과 catch문 모두에서 작성이 되어야하는데 만약 예외 상황이 여러개라면 해당 코드를 모든 catch 블록에 작성해야 할 것이다. 이는 매우 번거롭다.
  • 그래서 이를 위해 try 블록이 수행되면 어떤 경우에도 반드시 수행되는 블록인 finally가 존재한다.

🖥 try-catch-finally

package GueJavaPackage1;

import java.io.*;

public class ExceptionHandling2 {

	public static void main(String[] args) {
		FileInputStream fis = null;
		
		try {
			fis = new FileInputStream("a.txt");
		} catch (FileNotFoundException e) {
			System.out.println(e);
			return;
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			System.out.println("지구가 멸망해도 수행됨.");
		}
	}
}

입력받은 파일이 없는 경우에 파일을 찾을 수 없다는 예외가 출력된다. 즉, catch 문이 수행되었다.
그런데 catch 문에 return 문이 있음에도 finally 블록의 코드가 실행된 모습을 확인할 수 있다.
나중에 배우겠지만 이렇듯 마지막에 파일 입력 스트림을 닫는 코드를 구현해야 문제가 없다.


예외 처리의 기본을 배웠다.
다음은 예외 처리에 대해 조금 더 심화된 내용들을 다룬다.

사진 출처
🔗 TCP School

profile
Hodie mihi, Cras tibi

0개의 댓글