제이제이
article thumbnail

 

본 내용은 "윤성우의 열혈 Java 프로그래밍"를 참고로 정리한 내용입니다.

 

1. 예외처리


❓ 예외란?

🔥 프로그램이 실행 중에 발생하는 정상적이지 않은 상황(예외적인 상황)을 의미합니다.

 

🚨 그렇다면 오류는?

💡 오류는 대다수의 문법적인 실수를 의미합니다.
  • 따라서 오류는 컴파일 과정에서 나타나게 됩니다.

예외를 알아보기 위해 다음의 코드를 살펴봅시다.

import java.util.Scanner;

public class ExceptionCase{
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		System.out.print("a/b...a?");
		//int형 정수 입력
		int n1 = sc.nextInt();
		
		System.out.print("a/b...b?");
		//int형 정수 입력
		int n2 = sc.nextInt();
		System.out.printf("%d / %d = %d\\n",n1,n2,n1/n2);
		System.out.println("Good bye ~~!");	
	}
}

 

출력 결과

a/b...a? 8
a/b...b? 0
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at part18.ExceptionCase.main(ExceptionCase.java:14)

 

📋  분석

위의 코드를 분석해 봅시다. 위의 코드는 문법적으로 논리적으로 문제가 없습니다.

🚨 문제는 나누는 수가 0이 될 수 없음에도 0이 입력된 상황입니다.

 

이러한 상황을 “예외”라고 합니다.

  • 예외가 발생하는 순간에 프로그램은 종료가 됩니다. (가상 머신은 예외가 발생하면 그 내용을 간단히 출력하고 프로그램을 종료합니다.)

출력결과의 다음 문장을 보여줌으로써 프로그램에서 예외가 발생되었다는 것을 알려줍니다.

Exception in thread "main" java.lang.ArithmeticException: / by zero
	at part18.ExceptionCase.main(ExceptionCase.java:14)

 

의미

“0으로 / 연산을 하여 java.lang.ArithmethicException 예외가 발생하였다.”

 

+) 입력에서 또다른 예외가 발생할 수도 있습니다.

		System.out.print("a/b...a?");
		//int형 정수 입력
		int n1 = sc.nextInt();

 

🚨 숫자가 아닌 문자가 입력되어 다음과 같은 예외가 발생할 수 있습니다.

a/b...a? R
Exception in thread "main" java.util.InputMismatchException
	at java.base/java.util.Scanner.throwFor(Scanner.java:939)
	at java.base/java.util.Scanner.next(Scanner.java:1594)
	at java.base/java.util.Scanner.nextInt(Scanner.java:2258)
	at java.base/java.util.Scanner.nextInt(Scanner.java:2212)
	at part18.ExceptionCase.main(ExceptionCase.java:10)

 

처리 방법

  • 최소한 다음과 같은 예외의 원인을 설명하고 다시 실행되어야 합니다.

“숫자를 입력해야 합니다. 다시 실행해주세요”

 

🔎  출력 결과에서 보여지는 메시지를 다시 한번 확인해 봅시다.

  • java.lang.ArithmeticException
    • 수학 연산에서의 오류 상황을 의미하는 예외 클래스
  • java.util.InputMismatchException
    • 클래스 Scanner를 통한 값의 입력에서의 오류 상황을 의미하는 예외 클래스

💡 이처럼 자바는 예외 상황별로 그 상황을 알리기 위한 클래스를 정의하고 있습니다.

 

❗ 예외 클래스란?

🔥 자바에서 예외 상황별로 알리기 위한 클래스

 

해석

  1. 위의 코드 처럼 수학 연산관련 오류가 발생하면 가상머신은 예외 클래스 ArithmeticException의 인스턴스를 생성합니다.
  • 이 인스턴스를 프로그래머가 처리하면 예외는 처리된 것으로 간주하여 프로그램을 종료하지 않습니다.
  • 인스턴스를 처리하지 않으면 프로그램은 그냥 종료 됩니다.

 

🔥  예외를 처리하는 방법: Try ~ catch문

자바에서 예외를 처리할 때는 Try ~ Catch문을 사용합니다.

구조

try{
		//관찰 영역
}catch(Exception name) {
		//처리 영역
}

 

의미

🔥 try 영역에서 발생한 예외 상황을 catch 영역에서 처리합니다.

 

예시

  • ArithmeticException 예외를 처리하는 try ~ catch문
try{
		//관찰 영역
} catch(ArithmeticException e){
		//처리 영역
}

 

작동방식

1. try 영역의 실행 중간에 예외 상황이 발생합니다.

2. 가상머신이 ArithmeticException 인스턴스를 생성합니다.

3. 이 인스턴스는 메소드를 호출하듯이 catch구문의 매개변수 e에 전달됩니다.

4. 가상 머신은 catch 구문 안에서 무엇을 상관없이 예외가 처리된 것으로 간주하고 실행을 이어나갑니다.

import java.util.Scanner;

public class Exception2{
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);

		try{
        System.out.print("a/b...a?");
        
				int n1 = kb.nextInt();
        
				System.out.print("a/b...b?");
        int n2 = kb.nextInt();
        //예외 발생 지점
        System.out.printf("%d / %d = %d\\n",n1,n2,n1/n2);
		}catch(ArithmeticException e){
		  System.out.println(e.getMessage());
		}
		  System.out.println("Good Bye ~~~!");
 }
}

 

출력 결과

a/b...a? 2
a/b...b? 0
/ by zero
Good Bye ~~~!

 

📋  분석

위의 코드에서 예외가 발생되는 문장입니다.

  • n2가 0인상황에서 나눗셈을 진행하는 순간에 예외가 발생합니다.
//예외 발생 지점
System.out.printf("%d / %d = %d\\n", n1, n2, n1/n2);

 

그러면 이 순간 가상머신은 ArithmeticException 인스턴스를 생성합니다.

그리고 catch 영역에서 이 인스턴스를 인자로 받을 수 있는지 확인하고 받을 수 있다면 catch문에 인스턴스를 전달합니다.

💡 catch 영역으로 인스턴스 전달과정은 메소드 호출시의 인자 전달 과정과 동일합니다.
      즉, 예외의 전달 가능 여부는 catch 영역의 매개변수 선언을 통해 결정됩니다.

 

❗ catch 영역으로 예외 인스턴스가 전달이 되면 가성머신은 예외가 처리된 것으로 판단합니다.

 

+) catch영역의 getMessage 메소드 호출

System.out.println(e.getMessage());
  • 예외의 원인을 담고 있는 문자열을 반환합니다.

Try로 감싸야 할 영역의 결정

다음의 코드를 살펴봅시다.

try{
		//1번
		//2번 예외 발생 시점
		//3번
}catch (Exception e) {
	  //4번 
}
//예외 처리 후 실행 지점

 

과정

1. 2번 위치에서 예외가 발생하고 catch 영역으로 예외가 처리(4번)가 됩니다.

2. 이후 try문의 3번의 위치에서 실행을 이어나가는 것이 아닌 예외 처리 후의 실행 지점으로 이동하여 실행을 이어나가게 됩니다.

🔥 이러한 처리 이후의 실행 특성은 관련이 있는 작업들을 하나로 묶는데 도움이 됩니다.

 

다음의 코드를 살펴봅시다.

import java.util.Scanner;

public class Exception3 {
    public static void main(String[]args){
        Scanner kb = new Scanner(System.in);
        System.out.print("a/b...a?");
        int n1 = kb.nextInt(); //입력 오류 발생 가능성
        System.out.print("a/b ... b?");
        int n2 = kb.nextInt(); //입력 오류 발생 가능성
        System.out.printf("%d / %d = %d",n1,n2,n1/n2);
        System.out.println("Good bye ~~~!");
    }
}

 

출력 결과

a/b...a? R
Exception in thread "main" java.util.InputMismatchException
	at java.base/java.util.Scanner.throwFor(Scanner.java:939)
	at java.base/java.util.Scanner.next(Scanner.java:1594)
	at java.base/java.util.Scanner.nextInt(Scanner.java:2258)
	at java.base/java.util.Scanner.nextInt(Scanner.java:2212)
	at part18.Exception3.main(Exception3.java:9)
🚨 위의 코드에서 입력의 오류로 인해 InputMismatchException 예외가 발생될 수 있는 문장은 다음의 두 문장입니다.

 

int n1 = kb.nextInt();
int n2 = kb.nextInt();

 

🔎  Try ~ catch문을 쓰기전 확인

  • 변수 n1에 정수가 오지 않는다면 변수 n2에 정수가 입력되어도 연산을 진행하는 것에 의미가 없습니다.

→ 따라서 위의 코드의 다음 문장들은 하나의 작업으로 볼 수 있습니다.

// 이 문장은 ’하나의 작업’에서 제외 가능
				Scanner kb = new Scanner(System.in);
        System.out.print("a/b...a?");
        int n1 = kb.nextInt(); 
        System.out.print("a/b ... b?");
        int n2 = kb.nextInt(); 
        System.out.printf("%d / %d = %d",n1,n2,n1/n2);
        System.out.println("Good bye ~~~!");

 

⭕  Try ~ catch문으로 개선한 코드

방법1

import java.util.InputMismatchException;
import java.util.Scanner;

public class ExceptionCase4 {
    public static void main(String[]args){
        Scanner kb = new Scanner(System.in);

        try{
            System.out.print("a/b...a?");
            int n1 = kb.nextInt();
            System.out.print("a/b...b?");
            int n2 = kb.nextInt();
            System.out.printf("%d / %d = %d",n1,n2,n1/n2);

        }catch(ArithmeticException e) {
						e.getMessage();
				}
				}catch (InputMismatchException e){
            e.getMessage();
        }
        System.out.println("Good bye ~~!");
    }
}

 

방법2

  • 또한 catch구문안에서 이어서 처리할 수 있습니다.
import java.util.InputMismatchException;
import java.util.Scanner;

public class ExceptionCase5 {
    public static void main(String[]args){
        Scanner kb = new Scanner(System.in);

        try{
            System.out.print("a/b...a?");
            int n1 = kb.nextInt();
            System.out.print("a/b...b?");
            int n2 = kb.nextInt();
            System.out.printf("%d / %d = %d",n1,n2,n1/n2);

        }catch (ArithmeticException | InputMismatchException e){
            e.getMessage();
        }
        System.out.println("Good bye ~~!");
    }
}
💡 상황별 예외 처리 방식이 다르지 않을 때 방법2처럼 하나의 catch 구문 안에서 모든 예외를 처리하도록 묶을 수 있습니다.

Throwable 클래스와 예외 처리의 책임 전가

❓ Throwable 클래스란?

🔥 자바의 최상위 클래스인 java.lang.Objcet를 제외한 모든 예외클래스의 최상위 클래스입니다.

 

java.lang.Throwable //예외 클래스의 최상위 클래스

 

❗ Throwable 클래스의 메소드

  • Throwable 클래스에는 발생하는 예외의 정보를 알 수 있는 메소드가 정의되어 있습니다.
public String getMessage();
-> 예외의 원인을 담고 있는 문자열을 반환함

public void printStackTrace();
-> 예외가 발생한 위치와 호출된 메소드의 정보를 출력함

 

앞의 코드에서 getMessage메소드를 봤습니다. 이번에는 printStackTrace 메소드를 확인해 봅시다.

class ExceptionMessage{
	public static void md1(int n) {
		md2(n,0); //아래의 메소드 호출
	}
	public static void md2(int n1, int n2){
		int r = n1/n2; //예외 발생 지점
 }
	public static void main(String[] args){
		md1(3);
		System.out.println("Good bye ~~!");
	}
}

 

출력 결과

Exception in thread "main" java.lang.ArithmeticException: / by zero
	at part18.ExceptionMessage.md2(ExceptionMessage.java:8)
	at part18.ExceptionMessage.md1(ExceptionMessage.java:5)
	at part18.ExceptionMessage.main(ExceptionMessage.java:11)

 

그럼 printStackTrace 메소드의 기능 확인을 위해 다음 예제를 실행해봅시다.(예외가 발생할 수 밖에 없는 상황입니다.)

public class ExceptionMessage {
    public static void md1(int n){
        md2(n,0); //아래의 메소드 호출
    }
    public static void md2(int n1, int n2){
        int r = n1/n2; //예외 발생 지점
    }
    public static void main(String[]args){
        md1(3);
        System.out.println("Good bye~~~!");
    }
}

 

출력 결과

Exception in thread "main" java.lang.ArithmeticException: / by zero
	at part18.ExceptionMessage.md2(ExceptionMessage.java:8)
	at part18.ExceptionMessage.md1(ExceptionMessage.java:5)
	at part18.ExceptionMessage.main(ExceptionMessage.java:11)

 

분석

🔎 메소드 호출 흐름

1.main메소드 → 2.md1메소드 → 3. md2메소드

예외가 발생한 부분: md2 메소드

  • md2에서 해당 예외를 처리하지 않았습니다.
  • → 이러한 경우 가상머신은 md2 메소드를 호출한 md1메소드에게 예외처리의 책임을 넘깁니다.
    (예외처리의 책임이 넘어가면 예외처리의 책임을 넘긴 메소드의 호출은 종료됩니다.)
  • md1메소드에서도 해당 예외를 처리하지 않았습니다.
    (main메소드에서도 예외처리를 하지 않으면 JVM이 대신 예외처리를 합니다.)→이러한 경우 md1의 메소드를 호출한 main 메소드에 예외처리 책임을 넘기지 않습니다.

 

출력결과

출력 결과에 보이는 내용을 살펴봅시다.

// 0으로 /연산을 하여 ArithmeticException이 발생하였다.
java.lang.ArithmeticException: / by zero

//ExceptionMessage 클래스의 md2가 예외가 시작되었고
at part18.ExceptionMessage.md2(ExceptionMessage.java:8)

//ExceptionMessage 클래스의 md1으로 예외가 넘어갔으며
at part18.ExceptionMessage.md1(ExceptionMessage.java:5)

//ExceptionMessage 클래스의 main으로까지 예외가 넘어갔다.
at part18.ExceptionMessage.main(ExceptionMessage.java:11)

 

🔥 출력 결과(내용)을 확인하면 예외의 발생 및 이동경로를 확인할 수 있습니다.

 

⭕  예외처리

md2메소드에서 발생한 예외를 main메소드에서 예외를 처리하는 방식으로 코드를 개선해보겠습니다.

public class ExceptionMessage2{
	public static void md1(int n){
		md2(n,0); //md2 메소드의 예외가 넘어오게 됩니다.
	}

	public static void md2(int n1,int n2) {
		int r = n1/n2; //예외가 발생되는 부분입니다.
	}
	
	public static void main(String[]args){	
		try{
			md1(3); //md1메소드의 예외가 넘어오게 됩니다.
		}catch(Throwable e){
			e.printStackTrace();
		}
			System.out.println("Good bye~~~!");
	}
}

 

출력 결과

java.lang.ArithmeticException: / by zero
	at part18.ExceptionMessage2.md2(ExceptionMessage2.java:8)
	at part18.ExceptionMessage2.md1(ExceptionMessage2.java:5)
	at part18.ExceptionMessage2.main(ExceptionMessage2.java:12)
Good bye~~~!

 

분석

예외처리가 되는 try ~catch 구문을 살펴봅시다.

try {
      md1(3); // 이 지점에서 md1으로부터 예외가 넘어온다.
  }catch (Throwable e){
      e.printStackTrace();
  }

 

🚨 실제로 넘어오는 예외는 Throwable 인스턴스가 아닙니다.
      그러나 모든 예외 클래스가 Throwable을 상속하므로 상속 관계에 의해서 처리합니다.
  • 좋은 예외처리의 방식은 아닙니다.

 

catch구문에서 호출한 printStackTrace 메소드가 출력한 내용을 확인해봅시다.

→ 앞서 살펴봤던 가상머신이 예외를 처리할 때 출력하는 문장과 동일합니다.

 

이유

🔥 사실 가상머신도 예외의 처리과정에서 프로그램을 종료하기 전에 예외 인스턴스의 printStackTrace 메소드를 호출합니다.

예외 상황을 알리기 위해 정의된 클래스의 종류

자바에서 발생시키는 예외의 종류는 다양합니다.(예외 클래스도 다양하게 정의되었습니다)

대표적인 예외 클래스과 함께 해당 예외를 발생되는 상황을 살펴봅시다.

 

ArrayIndexOutOfBoundsException 예외

public class ArrayIndexOutOfBounds{
	public static void main(String[]args){
		int[] arr = {1,2,3};
	
		for(int i = 0;i<4;i++){
			System.out.println(arr[i]); //인덱스의 값3에 해당하는 배열의 값이 없어 오류가 발생합니다.
		}
	}
}

 

출력 결과

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
	at part18.ArrayIndexOutOfBounds.main(ArrayIndexOutOfBounds.java:8)
1
2
3

 

📋  발생하는 이유

  • 배열 접근에 잘못된 인덱스 값을 사용해서 발생됩니다.

 

ClassCastException 예외

class Board{ }
class PBoard extends Board{}

public class ClassCast{
	public static void main(String[]args){
		Board pbd1 = new PBoard();
		PBoard pbd2 = new PBoard(); //Ok!

		System.out.println("..intermediate location..");
		Board ebd1 = new Board();
		PBoard ebd2 = (PBoard) ebd1; //예외 발생
	}
}

 

출력 결과

.. intermediate location ..
Exception in thread "main" java.lang.ClassCastException: class part18.Board cannot be cast to class part18.PBoard (part18.Board and part18.PBoard are in unnamed module of loader 'app')
	at part18.ClassCast.main(ClassCast.java:13)

 

📋  발생하는 이유

  • 허용되지 않는 형 변환을 강제로 실행할 때 발생됩니다.

 

NullPointException 예외

public class NullPointer{
	public static void main(String[]args){
			String str = null;
			System.out.println(str); //null 출력
			int len = str.length(); //예외 발생
	}
}

 

출력 결과

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "str" is null
	at part18.NullPointer.main(NullPointer.java:7)
null

 

📋  발생하는 이유

  • null 이 저장된 참조변수를 대상으로 메소드를 호출할 때 발생합니다.

 

2. 예외 처리에 대한 나머지 설명들


❗ 자바에서의 예외는 중요하며 굉장히 양이 많습니다. 보다 더 많은 예외처리를 살펴봅시다.

🔎 예외 클래스의 구분

앞선 설명에서 예외 클래스의 최상위 클래스가 Throwable임을 알 수 있었습니다.

Throwable 클래스를 상속하는 예외 클래스는 크게 3가지 분류로 구별할 수 있습니다.

 

1.Error 클래스를 상속하는 예외 클래스

2.Exception 클래스를 상속하는 예외 클래스

3.RuntimeException 클래스를 상속하는 예외 클래스 (Exception 클래스를 상속합니다.)

 

Error 클래스를 상속하는 예외 클래스

발생원인과 예시

VirtualMachineError = 가상머신에 심각한 오류의 발생했음을 의미합니다.

IOError = 입출력과 관련하여 코드 수준 복구가 불가능한 오류가 발생했음을 의미합니다.

  • 자바 프로그램이 임의의 파일에 저장된 데이터를 읽던 중 갑자기 하드 디스크에 물리적 오류가 발생하여 더 이상 파일에 저장된 데이터를 읽을 수 없는 상황에서 발생됨을 의미합니다.
❗ 이러한 유형의 예외가 발생하면 프로그램이 종료되도록 두고 이후에 원인을 파악하는 과정이 이어져야 합니다.

 

+) VirtualMachineError를 상속하는 OutOfMemoryError 클래스

  • 프로그램의 실행에 필요한 메모리 공간이 부족한 상황에서 발생되는 예외입니다.
🚨 이 예외가 발생하면 메모리를 비효율적으로 또는 부적절하게 사용하는 부분의 코드를 수정해야 합니다.

 

RuntimeException 클래스를 상속하는 예외 클래스

ArithmeticException 클래스

ClassCastException 클래스

IndexOutOfBoundsException 클래스

Negative 클래스 = 배열 생성 시 길이를 음수로 지정하는 예외가 발생했음을 의미합니다.

NullPointException 클래스

ArrayStoreException 클래스 = 배열에 적절치 않은 인스턴스를 저장하는 예외가 발생했음을 의미합니다.

앞서 봤던 코드에서 RuntimeException 을 상속하는 예외 클래스에 대해서 try ~ catch문을 이용하여 살펴봤어씁니다.

🚨 그러나 RuntimeException 클래스를 상속하는 예외들은 대부분 예외처리를 하지 않습니다.

 

❓ 왜 일까?

다음의 코드를 살펴봅시다.

//NegativeArraySizeException 예외의 발생
Object[] array = new Object[-5];
  • 이 코드에서 발생하는 예외를 처리하는 것이 옳을까요?

코드를 수정하는 방식이 옳을 것입니다.

Exception 클래스를 상속하는 예외 클래스

🔥 RuntimeException 클래스를 상속하는 예외 클래스는 대부분 이 부류에서 제외 합니다.

 

이를 그림으로 자세하게 살펴보면 다음과 같습니다.

🚨 RuntimeException 클래스를 직접 혹은 간접적으로 상속하지 않고 Exception 클래스만 상속하는 예외 클래스에
       해당하는 내용입니다.

Exception을 상속하는 예외 클래스의 예외처리

Exception을 상속하는 예외 클래스의 중 대표적인 클래스 중 하나입니다.

java.io.IOException

 

 

다음의 코드를 통해 간단하게 어느 지점에서 예외가 발생되는지 살펴봅시다

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class IOExceptionCase {
    public static void main(String[]args){
        Path file = Paths.get("C:\\\\javastudy\\\\Simple.txt");
        BufferedWriter writer = null;
        try {
            writer = Files.newBufferedWriter(file); //IOException 발생 가능
            writer.write('A'); // IOException 발생 가능
            writer.write('Z'); // IOException 발생 가능

            if(writer != null)
            writer.close(); // IOException 발생 가능
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

위의 코드는 아래와 같은 경로에서 파일을 생성하고 그 안에 두 개의 문자를 저장하는 코드입니다.

 

🏁  경로

C:\\javastudy\\Simple .txt

위의 코드에서 try ~ catch문을 지우고 다시 코드를 컴파일 해봅시다.

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class IOExceptionCase2 {
    public static void main(String[]args){
        Path file = Paths.get("C:\\\\javastudy\\\\Simple.txt");
        BufferedWriter writer = null;
            writer = Files.newBufferedWriter(file); //IOException 발생 가능
            writer.write('A'); // IOException 발생 가능
            writer.write('Z'); // IOException 발생 가능

            if(writer != null)
            writer.close(); // IOException 발생 가능
        }
}

 

🚨 컴파일 오류가 일어나게 됩니다.

 

❓ 이유

IOException 예외 발생 가능성이 있는 ‘메소드의 호출문’에서 오류가 발생했기 때문입니다.

🔥 앞서 살펴 봤던 Error 클래스를 상속하는 예외와 RuntimeException 클래스를 상속하는 경우 예외 처리는 선택 사항입니다.

 

그러나 RuntimeException 클래스를 상속하지 않고 Exception 클래스를 상속하는 예외는 try ~ catch문으로 처리하거나 다른 영역으로 넘긴다고 명시해야 합니다.

이와 관련하여 다음의 코드를 살펴봅시다.

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class IOExceptionCase3 {
    public static void main(String[]args) {
        try {
            md1();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //IOException 예외 넘긴다고 명시
    public static void md1()throws IOException {
        md2();
    }
    public static void md2() throws IOException { // IOException 예외 넘긴다고 명시 !
        
        Path file = Paths.get("C:\\\\javastudy\\\\Simple.txt");
        BufferedWriter writer = null;
            writer = Files.newBufferedWriter(file); //IOException 발생 가능
            writer.write('A'); // IOException 발생 가능
            writer.write('Z'); // IOException 발생 가능

            if(writer != null)
            writer.close(); // IOException 발생 가능
        }
}

 

🔎 분석

위의 코드에서의 메소드 호출과정은 다음과 같습니다.

main -> md1 -> md2

이 중에서 md2 내에서 IOException 예외가 발생할 수 있습니다.

이를 해결하기 위해서는

방법1) try ~ catch문을 작성하거나

public static void md2() {
		Path file Paths.get( "C:\\\\javastudy\\\\Simple.txt");
 try {
}catch(IOException e) { e.printStackTrace();
	}
}

 

방법2) 예외의 처리를 이 메소드를 호출한 메소드에게 넘긴다고 표시해야 합니다.

public static void md2() throws IOException { // IOException 예외 발생하면 넘긴다!
 ...
}

 

❓ throws IOException이란?

🔥 IOException 예외가 메소드 내에서 발생할 경우 md2를 호출한 영역으로 예외의 처리를 넘긴다 (전달한다)는 의미입니다.
  • 예외를 넘기는 순간 md2 메소드의 호출은 종료됩니다.

 

그 다음 md1을 살펴봅시다.

🚨 md1 메소드에서 예외가 전달되는 경우에도 md1 메소드에서 해당 예외를 처리해야 합니다.

“md2 내에서 발생한 예외가 md1 메소드로 전달될 수 있으므로 md1메소드에서도 예외를 처리해야 합니다”

방법1)md1도 try ~ catch문을 작성하거나

public static void md1() {
		try{
			md2(); //IOException 예외가 발생할 수 있는(넘어올 수 있는) 메소드 호출
	}catch(IOException e){
		e.printStackTrace();
  }

 

방법2) md1도 예외의 처리를 이 메소드를 호출한 메소드에게 넘긴다고 표시해야 합니다.

public static void md1() throws IOException{ //IOException 예외가 발생하면 넘긴다.
		md2();
}

마찬가지로 main 또한 IOException 예외가 전달될 수 md1메소드를 호출함으로 예외를 처리해야 합니다.

방법1 = try ~ catch문을 작성하거나

방법2 = md1도 예외의 처리를 이 메소드를 호출한 메소드에게 넘긴다고 표시해야 합니다.

🚨 main 메소드도 예외를 넘기게 되면 이 예외는 main메소드를 호출한 가상머신에게 넘어가게 됩니다.
  • 가상 머신에 넘어가게 되면 프로그램은 종료가 됩니다.

 

📒 Reference (참고 자료)


  1. 윤성우의 열혈 자바
  2. 티스토리 블로그
 

[자바] 예외처리 (2) - 예외클래스의 구조

이 글은 PC 버전 TISTORY에 최적화 되어있습니다. 서론 이번에는 예외 클래스의 계층구조와 Exception 클래스에서 Runtime Exception 클래스를 제외한 Checked Exception 과 RuntimeException인 UnChecked Exception에 대해

itmining.tistory.com

 

profile

제이제이

@아사비치즈스틱

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!