πŸ“‚ JAVA/μ£Όμš” κ°œλ…

μ˜ˆμ™Έμ²˜λ¦¬(Exception Handling) - (1)

Amenable 2023. 1. 28. 14:39

  μžλ°”μ—μ„œλŠ” μ‹€ν–‰ μ‹œ(runtime) λ°œμƒν•  수 μžˆλŠ” ν”„λ‘œκ·Έλž¨ 였λ₯˜λ₯Ό 'μ—λŸ¬(Error)'와 'μ˜ˆμ™Έ(Exception)'둜 κ΅¬λΆ„ν•œλ‹€. μ—λŸ¬λŠ” λ©”λͺ¨λ¦¬ λΆ€μ‘±(OutOfMemoryError)μ΄λ‚˜ μŠ€νƒμ˜€λ²„ν”Œλ‘œμš°(StackOverflowError)와 같이 일단 λ°œμƒν•˜λ©΄ 볡ꡬ할 수 μ—†λŠ” μ‹¬κ°ν•œ 였λ₯˜μ΄κ³ , μ˜ˆμ™ΈλŠ” λ°œμƒν•˜λ”λΌλ„ 수슡될 수 μžˆλŠ” 비ꡐ적 덜 μ‹¬κ°ν•œ 것이닀.

  μ—λŸ¬λŠ” ν”„λ‘œκ·Έλž¨ μ½”λ“œμ— μ˜ν•΄μ„œ 수슡될 수 μ—†κ³  μ˜ˆμ™ΈλŠ” 수슡될 수 μžˆμœΌλ―€λ‘œ, μ˜ˆμ™Έ 처리(Exception Handling)λ₯Ό 톡해 ν•΄λ‹Ή 상황을 μΈμ‹ν•˜κ³  λŒ€μ²˜ν•˜λ„λ‘ ν•œλ‹€.

 

1. μ˜ˆμ™Έ 클래슀의 λΆ„λ₯˜ 🎹

μ˜ˆμ™Έ 클래슀의 계측ꡬ쑰

  μ˜ˆμ™Έ 클래슀의 계측 κ΅¬μ‘°λŠ” 크게 3κ°€μ§€λ‘œ λ‚˜λˆ„μ–΄ λ³Ό 수 μžˆλ‹€. μ™Όμͺ½μ— μžˆλŠ” Error, νŒŒλž€μƒ‰μœΌλ‘œ ν‘œμ‹œλœ Checked Exception 계열, μ£Όν™©μƒ‰μœΌλ‘œ ν‘œμ‹œλœ Unchecked Exception 계열(= RunTime Exception 계열)이 μžˆλ‹€.

  CheckedException 계열은 μ‚¬μš©μžμ˜ μ‹€μˆ˜μ™€ 같은 외적인 μš”μΈμ— μ˜ν•΄ λ°œμƒν•˜λŠ” μ˜ˆμ™Έμ΄λ‹€. 예λ₯Ό λ“€μ–΄ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” 파일의 이름을 μž…λ ₯ν–ˆλ‹€λ˜κ°€(FileNotFoundException), μ‹€μˆ˜λ‘œ 클래슀의 이름을 잘λͺ» μ μ—ˆλ‹€λ˜κ°€(ClassNotFoundException), λ˜λŠ” μž…λ ₯ν•œ 데이터 ν˜•μ‹μ΄ 잘λͺ»λœ(DataFormat Exception) κ²½μš°μ— λ°œμƒν•œλ‹€. ν•΄λ‹Ή κ²½μš°μ—λŠ” μ˜ˆμ™Έμ— λŒ€ν•œ λŒ€μ²˜ μ½”λ“œκ°€ μ—†μœΌλ©΄ 컴파일이 μ§„ν–‰λ˜μ§€ μ•ŠλŠ”λ‹€. 

  Unchecked Exception 계열(= RunTime Exception 계열)은 ν”„λ‘œκ·Έλž˜λ¨Έμ˜ μ‹€μˆ˜λ‘œ λ°œμƒν•˜λŠ” μ˜ˆμ™Έμ΄λ‹€. 예λ₯Ό λ“€μ–΄ λ°°μ—΄μ˜ λ²”μœ„λ₯Ό λ²—μ–΄λ‚œλ‹€λ˜κ°€(ArraryIndexOutOfBoundsException), 값이 null인 μ°Έμ‘°λ³€μˆ˜μ˜ 멀버λ₯Ό ν˜ΈμΆœν•˜λ € ν–ˆλ‹€λ˜κ°€(NullPointerException), 클래슀 κ°„μ˜ ν˜•λ³€ν™˜μ„ 잘λͺ»ν–ˆλ‹€λ˜κ°€(ClassCastException), μ •μˆ˜λ₯Ό )으둜 λ‚˜λˆ„λ €κ³ (ArithmeticException)ν•˜λŠ” κ²½μš°μ— λ°œμƒν•œλ‹€. μ΄λŠ” μ˜ˆμ™Έμ— λŒ€ν•œ λŒ€μ²˜ μ½”λ“œκ°€ 없더라도 μ»΄νŒŒμΌμ€ 진행이 λœλ‹€.

 

2. try-catch문 🎸

try {
    // μ˜ˆμ™Έκ°€ λ°œμƒν•  κ°€λŠ₯성이 μžˆλŠ” μ½”λ“œλ“€μ„ λ„£λŠ”λ‹€.
} catch (Exception e) {
    // μ˜ˆμ™Έλ₯Ό μ²˜λ¦¬ν•˜κΈ° μœ„ν•œ μ½”λ“œλ₯Ό λ„£λŠ”λ‹€.
}

  μ˜ˆμ™Έκ°€ λ°œμƒν•˜λ©΄, λ°œμƒν•œ μ˜ˆμ™Έμ— ν•΄λ‹Ήν•˜λŠ” 클래슀의 μΈμŠ€ν„΄μŠ€κ°€ λ§Œλ“€μ–΄μ§„λ‹€. κ·Έλž˜μ„œ λ§Œμ•½ μ˜ˆμ™Έκ°€ λ°œμƒν•œ λ¬Έμž₯이 tryλΈ”λŸ­μ— ν¬ν•¨λ˜μ–΄ μžˆλ‹€λ©΄, 이 μ˜ˆμ™Έλ₯Ό μ²˜λ¦¬ν•  수 μžˆλŠ” catch λΈ”λŸ­μ΄ μžˆλŠ”μ§€ 찾게 λœλ‹€. μ μ ˆν•œ catchλΈ”λŸ­μ„ 찾게 되면 catchλΈ”λŸ­ μ•ˆμ˜ λ‚΄μš©μ„ μˆ˜ν–‰ν•˜κ³  try-catch문을 λΉ μ Έλ‚˜κ°„λ‹€.

  catchλΈ”λŸ­μ˜ μ˜ˆμ™Ένƒ€μž… λ²”μœ„κ°€ λ„ˆλ¬΄ 큰 경우 μ˜ˆμ™Έκ°€ λ°œμƒν•˜μ§€λ§Œ ꡬ체적인 μ˜ˆμ™Έμ— λŒ€ν•΄μ„œ μ•Œμ§€ λͺ»ν•˜κ²Œ 되고, λ§Œμ•½ catchλΈ”λŸ­μ˜ μ˜ˆμ™Ένƒ€μž… λ²”μœ„ λ„ˆλ¬΄ μž‘μ€ κ²½μš°μ—λŠ” μ˜ˆμ™Έκ°€ μ²˜λ¦¬λ˜μ§€ μ•ŠλŠ” λ¬Έμ œκ°€ λ°œμƒν•œλ‹€. κ·Έλž˜μ„œ μ•„λž˜μ™€ 같이 μž‘μ€ λ²”μœ„μ—μ„œ 큰 λ²”μœ„λ‘œ catchλΈ”λŸ­μ˜ 흐름을 μ œμ–΄ν•  ν•„μš”κ°€ μžˆλ‹€. (μ˜ˆμ™Έ ν΄λž˜μŠ€λŠ” μ˜ˆμ™Ένƒ€μž… λ²”μœ„μ˜ 크기에 의미λ₯Ό 두기 μœ„ν•˜μ—¬ μž„μ˜λ‘œ μž‘μ„±ν•œ 것이닀.)

try {
    // μ˜ˆμ™Έκ°€ λ°œμƒν•  κ°€λŠ₯성이 μžˆλŠ” μ½”λ“œλ“€μ„ λ„£λŠ”λ‹€.
} catch (SubSubException e) {
    // μ˜ˆμ™Έλ₯Ό μ²˜λ¦¬ν•˜κΈ° μœ„ν•œ μ½”λ“œλ₯Ό λ„£λŠ”λ‹€.
} catch (SubException e) {
    // μ˜ˆμ™Έλ₯Ό μ²˜λ¦¬ν•˜κΈ° μœ„ν•œ μ½”λ“œλ₯Ό λ„£λŠ”λ‹€.
} catch (Exception e) {
    // μ˜ˆμ™Έλ₯Ό μ²˜λ¦¬ν•˜κΈ° μœ„ν•œ μ½”λ“œλ₯Ό λ„£λŠ”λ‹€.
}

 

  JDK1.7λΆ€ν„°λŠ” λ©€ν‹° catch λΈ”λŸ­μ„ μ§€μ›ν•˜κ³  μžˆλ‹€. μ΄λŠ” μ—¬λŸ¬ catch λΈ”λŸ­μ„ '|' 기호λ₯Ό ν†΅ν•΄μ„œ ν•˜λ‚˜λ‘œ ν•©μΉ  수 있게 ν•΄ μ€€λ‹€. μ£Όμ˜ν•  점은 μ˜ˆμ™Έ ν΄λž˜μŠ€κ°€ 쑰상과 μžμ†μ˜ 관계가 있으면 μ•ˆ λœλ‹€.

try {
    ...
} catch (ParentException | ChildException e) { // Error
    ...
} 

try {
    ...
} catch (ParentExceptionA | ParentExceptionB e) { // OK
    ...
} 

try {
    ...
} catch (ChildExceptionA | ChildExceptionB e) { // OK
    ...
}

 

3. μ˜ˆμ™Έμ— λŒ€ν•œ 정보 πŸ“―

  μ˜ˆμ™Έκ°€ λ°œμƒν–ˆμ„ λ•Œ μƒμ„±λ˜λŠ” μ˜ˆμ™Έ 클래슀의 μΈμŠ€ν„΄μŠ€μ—λŠ” λ°œμƒν•œ μ˜ˆμ™Έμ— λŒ€ν•œ 정보가 λ‹΄κ²¨μžˆλ‹€. getMessage()와 printStackTrace()λ₯Ό ν†΅ν•΄μ„œ 이 정보듀을 μ‚¬μš©ν•  수 μžˆλ‹€.

  getMessage()λŠ” λ°œμƒν•œ μ˜ˆμ™Έν΄λž˜μŠ€μ˜ μΈμŠ€ν„΄μŠ€μ— μ €μž₯된 λ©”μ‹œμ§€λ₯Ό 얻을 수 있고, printStackTrace()λŠ” μ˜ˆμ™Έλ°œμƒ λ‹Ήμ‹œμ˜ ν˜ΈμΆœμŠ€νƒ(Call Stack)에 μžˆμ—ˆλ˜ λ©”μ„œλ“œμ˜ 정보와 μ˜ˆμ™Έ λ©”μ‹œμ§€λ₯Ό 화면에 좜λ ₯ν•œλ‹€.

public class Main {
	public static void main(String[] args) {
		int N = 10;
		System.out.println("N = " + N);
		try {
			System.out.println("N / 5 = " + N / 5);
			System.out.println("N / 2 = " + N / 2);
			System.out.println("N / 0 = " + N / 0); // μ˜ˆμ™Έ λ°œμƒ
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("e.getMessage λ‚΄μš© : " + e.getMessage());
		}
	}
}

// 좜λ ₯ λ‚΄μš©
// N = 10
// N / 5 = 2
// N / 2 = 5
// e.getMessage λ‚΄μš© : / by zero
// java.lang.ArithmeticException: / by zero
//  	at com.amenable.Main.main(Main.java:8)

 

4. λ©”μ„œλ“œ μ˜ˆμ™Έ μ„ μ–Έ πŸ₯

void method1() throws Exception {
    ...
}

void method2() throws Exceptoin1, Exception2, Exception3 {
    ...
}

  μœ„μ™€ 같이 λ©”μ„œλ“œ μ˜ˆμ™Έ 선언을 해쀄 수 μžˆλ‹€. μ΄λŠ” μ˜ˆμ™Έλ₯Ό μ²˜λ¦¬ν•œλ‹€κΈ°λ³΄λ‹€λŠ” μžμ‹ μ„ ν˜ΈμΆœν•œ λ©”μ„œλ“œμ—κ²Œ μ˜ˆμ™Έμ²˜λ¦¬λ₯Ό λ– λ§‘κΈ°λŠ” 것이닀. λ‹¨μˆœνžˆ 전달을 ν•˜λŠ” κ²ƒμ΄λ―€λ‘œ μ–΄λŠ ν•œ κ³³μ—μ„œλŠ” λ°˜λ“œμ‹œ try-catch문으둜 μ˜ˆμ™Έμ²˜λ¦¬λ₯Ό ν•΄μ£Όμ–΄μ•Ό ν•œλ‹€.

  κ·Έλ ‡λ‹€λ©΄ κ·Έλƒ₯ ν•΄λ‹Ή λ©”μ„œλ“œμ—μ„œ λ°”λ‘œ μ˜ˆμ™Έμ²˜λ¦¬λ₯Ό ν•΄μ£Όλ©΄ λ˜λŠ”λ° μ™œ 전달을 ν• κΉŒ? λ‹€μ–‘ν•œ μ΄μœ κ°€ μžˆμ„ 수 μžˆκ² μ§€λ§Œ 그쀑 ν•œ κ°€μ§€ μ΄μœ λŠ” 'ν˜ΈμΆœν•œ λ©”μ„œλ“œμ—μ„œ μ˜ˆμ™Έκ°€ λ°œμƒν–ˆλ‹€λŠ” 사싀을 μ•Œ 수 있게 ν•˜κΈ° μœ„ν•¨'이닀. λ¨Όμ € μ½”λ“œλ₯Ό 보자.

public class Main {
	public static void main(String[] args) {
		method();
	}

	static void method() {
		try {
			throw new Exception();
		} catch (Exception e) {
			System.out.println("methodμ—μ„œ μ˜ˆμ™Έ 처리");
			e.printStackTrace();
		}
	}
}

//methodμ—μ„œ μ˜ˆμ™Έ 처리
//java.lang.Exception
//	at com.amenable.Main.method(Main.java:8)
//	at com.amenable.Main.main(Main.java:3)

  μœ„μ˜ μ½”λ“œμ²˜λŸΌ μž‘μ„±ν•˜λ©΄ mainμ—μ„œλŠ” μ˜ˆμ™Έκ°€ λ°œμƒν–ˆλ‹€λŠ” 사싀쑰차 λͺ¨λ₯΄κ²Œ λœλ‹€. ν•˜μ§€λ§Œ methodμ—μ„œ μ˜ˆμ™Έλ₯Ό λ„˜κ²¨μ£Όλ©΄ mainμ—μ„œ methodλ₯Ό ν˜ΈμΆœν•œ λΌμΈμ—μ„œ μ˜ˆμ™Έκ°€ λ°œμƒν•œλ‹€λŠ” 것을 μ•Œ 수 있고 이에 λŒ€ν•΄μ„œ 처리λ₯Ό ν•  수 μžˆλ‹€.

public class Main {
	
	public static void main(String[] args) {
		method(); // 컴파일 μ•ˆλ¨. μ˜ˆμ™Έμ²˜λ¦¬ ν•΄μ€˜μ•Ό 함
	}

	static void method() throws Exception {
		throw new Exception();
	}
}
public class Main {
	
	public static void main(String[] args) {
		try {
			method();
		}
		catch(Exception e) {
			System.out.println("mainμ—μ„œ μ˜ˆμ™Έμ²˜λ¦¬");
			e.printStackTrace();
		}
	}

	static void method() throws Exception {
		throw new Exception();
	}
}
//mainμ—μ„œ μ˜ˆμ™Έμ²˜λ¦¬
//java.lang.Exception
//	at com.amenable.Main.method(Main.java:14)
//	at com.amenable.Main.main(Main.java:5)

 

ν•΄λ‹Ή 글은 남ꢁ μ„±λ‹˜μ˜ Java의 정석을 읽고 μž‘μ„±ν•œ κ²ƒμž…λ‹ˆλ‹€.