item 69 SeungminLee - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

item 69

μ˜ˆμ™ΈλŠ” μ§„μ§œ μ˜ˆμ™Έ μƒν™©μ—μ„œλ§Œ μ‚¬μš©ν•˜λΌ

λ¬΄ν•œ 루프λ₯Ό λŒλ‹€κ°€ μ˜ˆμ™Έλ₯Ό λ§Œλ‚˜ λλ‚˜λŠ” μ½”λ“œ VS for λ¬Έ

// μ˜ˆμ™Έλ₯Ό μ‚¬μš©ν•΄ λ³΅μž‘ν•˜κ²Œ λ§Œλ“  μ½”λ“œ
try{
	int i = 0;
	while(true)
		range[i++].climb();
	} catch (ArrayIndexOutOfBoundsException e) {
			//
	}

// ν‘œμ€€μ μΈ κ΄€μš©κ΅¬λŒ€λ‘œ μž‘μ„±ν•œ μ½”λ“œ 
for (Mountain m : range)
	m.climb();

μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œμΌœ μ•„μ£Ό λ”μ°ν•œ λ°©λ²•μœΌλ‘œ λ°˜λ³΅μ„ μ’…λ£Œν•œ μ½”λ“œκ°€ 예둜 λ‚˜μ™€μžˆλ‹€. μ™œ μ•ŒκΈ°μ‰½κ³  λ³΄κΈ°μ‰¬μš΄ ν‘œμ€€μ μΈ κ΄€μš©κ΅¬ forλ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  μ˜ˆμ™Έλ₯Ό μ‚¬μš©ν–ˆμ„κΉŒ?

  • 잘λͺ»λœ 좔둠을 근거둜 μ„±λŠ₯을 높여보렀고 ν•œ 것이닀.
  • JVM은 배열에 μ ‘κ·Όν•  λ•Œλ§ˆλ‹€ 경계λ₯Ό λ„˜μ§€ μ•ŠλŠ”μ§€ κ²€μ‚¬ν•˜λŠ”λ°, 일반적인 λ°˜λ³΅λ¬Έλ„ λ°°μ—΄ 경계에 λ„λ‹¬ν•˜λ©΄ μ’…λ£Œν•œλ‹€. β†’ 이 검사λ₯Ό λ°˜λ³΅λ¬Έμ—λ„ λͺ…μ‹œν•˜λ©΄ 일이 μ€‘λ³΅λœλ‹€ β†’ μ€‘λ³΅λ˜λ‹ˆκΉŒ ν•˜λ‚˜λ₯Ό μƒλž΅ν•˜μž! λŒ€μ‹  μ˜ˆμ™Έλ₯Ό λ„£μž. β†’ κ·ΈλŸ¬λ‚˜ 잘λͺ»λœ 좔둠이닀.
    1. μ˜ˆμ™ΈλŠ” μ˜ˆμ™Έμ˜ 상황에 μ“Έ μš©λ„λ‘œ μ„€κ³„λ˜μ—ˆμœΌλ―€λ‘œ JVM κ΅¬ν˜„μž μž…μž₯μ—μ„œλŠ” λͺ…ν™•ν•œ κ²€μ‚¬λ§ŒνΌ(일반적으둜 μ‚¬μš©λ˜λŠ” κΈ°λŠ₯)만큼 λΉ λ₯΄κ²Œ λ§Œλ“€μ–΄μ•Ό ν•  ν•„μš”λ₯Ό λͺ» λŠλ‚€λ‹€. μ΅œμ ν™”μ— λ³„λ‘œ 신경을 쓰지 μ•Šμ•˜λ‹€λŠ” λœ»μ΄λ‹€.
    2. 배열을 μˆœνšŒν•˜λŠ” ν‘œμ€€ κ΄€μš©κ΅¬λŠ” μ•žμ„œ μ–ΈκΈ‰ν•œ 쀑볡 검사λ₯Ό μˆ˜ν–‰ν•˜μ§€ μ•ŠλŠ”λ‹€. JVM이 μ•Œμ•„μ„œ μ΅œμ ν™”λ₯Ό ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.
    3. try-catch 블둝 μ•ˆμͺ½μ— μžˆλŠ” μ½”λ“œλŠ” JVM이 μ μš©ν•  수 μžˆλŠ” μ΅œμ ν™”κ°€ μ œν•œλœλ‹€.

싀상은 에외λ₯Ό μ‚¬μš©ν•œ μͺ½μ΄ ν‘œμ€€ κ΄€μš©κ΅¬λ³΄λ‹€ 훨씬 λŠλ¦¬λ‹€. μ˜ˆμ™Έλ₯Ό μ‚¬μš©ν•œ 반볡문의 해악은 μ½”λ“œλ₯Ό ν—·κ°ˆλ¦¬κ²Œ ν•˜κ³  μ„±λŠ₯을 λ–¨μ–΄λœ¨λ¦¬λŠ”λ°μ„œ λλ‚˜μ§€ μ•ŠλŠ”λ‹€. 심지어 μ œλŒ€λ‘œ λ™μž‘ν•˜μ§€ μ•Šμ„ μˆ˜λ„ μžˆλ‹€. 반볡문 μ•ˆμ— 버그가 μˆ¨μ–΄μžˆλ‹€λ©΄ 흐름 μ œμ–΄μ— 쓰인 μ˜ˆμ™Έκ°€ 이 버그λ₯Ό 숨겨 디버깅을 훨씬 μ–΄λ ΅κ²Œ ν•  것이닀.

β†’ 반볡문의 λͺΈμ²΄μ—μ„œ ν˜ΈμΆœν•œ λ©”μ„œλ“œκ°€ λ‚΄λΆ€μ—μ„œ κ΄€λ ¨ μ—†λŠ” 배열을 μ‚¬μš©ν•˜λ‹€κ°€ ArrayIndexOutOfBoundsException을 μΌμœΌμΌ°λ‹€λ©΄ ν‘œμ€€ κ΄€μš©μ–΄κ΅¬μ—μ„œλŠ” ν•΄λ‹Ή μŠ€λ ˆλ“œλ₯Ό 즉각 μ’…λ£Œν•  것이닀. κ·ΈλŸ¬λ‚˜ μ˜ˆμ™Έλ₯Ό μ‚¬μš©ν–ˆλ‹€λ©΄ 반λͺ©λ¬Έμ€ 버그 λ•Œλ¬Έμ— 값이 잘λͺ»λ˜μ—ˆλŠ”데도 정상적 μž‘λ™μ΄λΌ μƒκ°ν•˜μ—¬ 상황을 μ˜€ν•΄ν•˜κ³  λ„˜μ–΄κ°„λ‹€.

μ˜ˆμ™ΈλŠ” 였직 예회 μƒν™©μ—μ„œλ§Œ 써야 ν•œλ‹€. μ ˆλŒ€λ‘œ 일상적인 μ œμ–΄ νλ¦„μš©μœΌλ‘œ μ“°μ—¬μ„  μ•ˆ λœλ‹€.

ν‘œμ€€μ μ΄κ³  μ‰½κ²Œ μ΄ν•΄λ˜λŠ” κ΄€μš©κ΅¬λ₯Ό μ‚¬μš©ν•˜κ³ , μ„±λŠ₯ κ°œμ„ μ„ λͺ©μ μœΌλ‘œ κ³Όν•˜κ²Œ 머리λ₯Ό μ“΄ 기법은 μžμ œν•˜μž. μ‹€μ œλ‘œ μ„±λŠ₯이 쒋아지더라도 μžλ°” ν”Œλž«νΌμ΄ κΎΈμ€€νžˆ κ°œμ„ λ˜κ³  μžˆμœΌλ‹ˆ μ΅œμ ν™”λ‘œ 얻은 μƒλŒ€μ μΈ μ„±λŠ₯ μš°μœ„κ°€ μ˜€λž˜κ°€μ§€ μ•Šμ„ 수 μžˆλ‹€. 반면 κ³Όν•˜κ²Œ μ˜λ¦¬ν•œ 기법에 μˆ¨κ²¨μ§„ λ―Έλ¬˜ν•œ λ²„κ·Έμ˜ νŽ˜ν•΄μ™€ μ–΄λ €μ›Œμ§„ μœ μ§€λ³΄μˆ˜ λ¬Έμ œλŠ” 계속 μ΄μ–΄μ§ˆ 것이닀.

잘 μ„€κ³„λœ API라면 ν΄λΌμ΄μ–ΈνŠΈκ°€ 정상적인 μ œμ–΄ νλ¦„μ—μ„œ μ˜ˆμ™Έλ₯Ό μ‚¬μš©ν•  일이 μ—†κ²Œ ν•΄μ•Ό ν•œλ‹€.

νŠΉμ • μƒνƒœμ—μ„œλ§Œ ν˜ΈμΆœν•  수 μžˆλŠ” 'μƒνƒœ 의쑴적' λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•˜λŠ” ν΄λž˜μŠ€λŠ” 'μƒνƒœ 검사' λ©”μ„œλ“œκ³  ν•¨κ»˜ μ œκ³΅ν•΄μ•Ό ν•œλ‹€. (ex: Iterator μΈν„°νŽ˜μ΄μŠ€μ˜ next와 hasNext

// μƒνƒœ 검사 λ©”μ„œλ“œ μ‚¬μš©!
for (Iterator<Foo> i = collection.iterator(); i.hasNext(); ) {
		Foo foo = i.next();
		....
}

// μƒνƒœ 검사 λ©”μ„œλ“œκ°€ μ—†λ‹€λ©΄ ν΄λΌμ΄μ–ΈνŠΈκ°€ ν•˜κ²Œ 될 일
// μ ˆλŒ€ 이런 μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚€λŠ” λ°©μ‹μœΌλ‘œ μ»¬λ ‰μ…˜ μˆœνšŒν•˜μ§€ 말 것

try {
	Iterator<Foo> i = collection.iterator();
	while(true) {
		Foo foo = i.next();
		...
		}
	} catch (NoSuchElementException e) {
	}

μƒνƒœ 검사 λ©”μ„œλ“œκ°€ μ—†μ—ˆλ‹€λ©΄ μš°λ¦¬λŠ” λ°˜λ³΅λ¬Έμ— 에외λ₯Ό μ‚¬μš©ν•΄μ„œ μž₯ν™©ν•˜κ³  ν—·κ°ˆλ¦¬κ³ , 속도도 느리고 μ—‰λš±ν•œ κ³³μ—μ„œ λ°œμƒν•œ 버그λ₯Ό μˆ¨κΈ°λŠ” μ½”λ“œλ₯Ό μž‘μ„±ν•˜κ²Œ λœλ‹€. 그런데 μƒνƒœ 검사 λ©”μ„œλ“œ λŒ€μ‹  μ‚¬μš©ν•  수 μžˆλŠ” 선택지도 μžˆλ‹€. μ˜΅μ…”λ„ ν˜Ήμ€ nullκ³Ό 같은 νŠΉμˆ˜ν•œ 값을 λ°˜ν™˜ν•˜λŠ” 것이닀!

μƒνƒœκ²€μ‚¬ λ©”μ„œλ“œμ™€ μ˜΅μ…”λ„μ€ 각각 μ–Έμ œ μ‚¬μš©ν•΄μ•Ό ν• κΉŒ?

  1. μ™ΈλΆ€ 동기화 없이 μ—¬λŸ¬ μŠ€λ ˆλ“œκ°€ λ™μ‹œμ— μ ‘κ·Όν•  수 μžˆκ±°λ‚˜ μ™ΈλΆ€ μš”μΈμœΌλ‘œ μƒνƒœκ°€ λ³€ν•  수 μžˆλ‹€λ©΄ μ˜΅μ…”λ„μ΄λ‚˜ νŠΉμ • 값을 μ‚¬μš©ν•œλ‹€. μƒνƒœ 검사 λ©”μ„œλ“œμ™€ μƒνƒœ μ˜μ‘΄λ©”μ„œλ“œ 호좜 사이에 객체의 μƒνƒœκ°€ λ³€ν•  수 있기 λ•Œλ¬Έμ΄λ‹€.
  2. μ„±λŠ₯이 μ€‘μš”ν•œ μƒν™©μ—μ„œ μƒνƒœ 검사 λ©”μ„œλ“œκ°€ μƒνƒœ 의쑴적 λ©”μ„œλ“œμ˜ μž‘μ—… 일뢀λ₯Ό 쀑볡 μˆ˜ν–‰ν•œλ‹€λ©΄ μ˜΅μ…”λ„μ„ λ°˜ν™˜ν•˜μž.
  3. 이외에 λͺ¨λ“  κ²½μš°μ—” μƒνƒœ 검사 λ©”μ„œλ“œ 방식이 쑰금 더 λ‚«λ‹€. 가독성이 살짝 더 μ’‹κ³ , 잘λͺ» μ‚¬μš©ν–ˆμ„ λ•Œ λ°œκ²¬λ„ 쉽닀. λ˜ν•œ μƒνƒœ 검사 λ©”μ„œλ“œ ν˜ΈμΆœμ„ κΉœλΉ‘ν–ˆλ‹€λ©΄ μƒνƒœ 의쑴 λ©”μ„œλ“œκ°€ μ˜ˆμ™Έλ₯Ό ν™•μ‹€ν•˜κ²Œ λ˜μ Έμ„œ 버그λ₯Ό 잘 보여쀄 것이닀.

핡심정리

μ˜ˆμ™ΈλŠ” μ˜ˆμ™Έ μƒν™©μ—μ„œ μ“Έ μ˜λ„λ‘œ μ„€κ³„λ˜μ—ˆλ‹€. 정상적인 μ œμ–΄ νλ¦„μ—μ„œ μ‚¬μš©ν•΄μ„œλŠ” μ•ˆλ˜λ©°, 이λ₯Ό ν”„λ‘œκ·Έλž˜λ¨Έμ—κ²Œ κ°•μš”ν•˜λŠ” APIλ₯Ό λ§Œλ“€μ–΄μ„œλ„ μ•ˆλœγ„·

⚠️ **GitHub.com Fallback** ⚠️