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

μ˜ˆμ™Έ 처리

μ˜ˆμ™Έλ₯Ό μ œλŒ€λ‘œ ν™œμš©ν•œλ‹€λ©΄ ν”„λ‘œκ·Έλž¨μ˜ 가독성, μ‹ λ’°μ„±, μœ μ§€λ³΄μˆ˜μ„±μ΄ λ†’μ•„μ§€μ§€λ§Œ 잘λͺ» μ‚¬μš©ν•˜λ©΄ λ°˜λŒ€μ˜ 효과λ₯Ό 초래

μ˜ˆμ™Έλ₯Ό 효과적으둜 ν™œμš©ν•˜λŠ” 지침을 닀룬닀.

λ°°μ—΄μ˜ μ›μ†Œλ₯Ό μˆœνšŒν•˜λŠ” μ½”λ“œ

μ˜ˆμ™Έλ₯Ό 잘λͺ» μ‚¬μš©ν•œ μ˜ˆμ‹œ
try {
   int i=0;
   while(true)
     range[i++].climb();

} catch (ArrayIndexOutOfBoundsException e) {
}

μœ„ μ½”λ“œλ₯Ό ν‘œμ€€μ μΈ κ΄€μš©κ΅¬λŒ€λ‘œ μž‘μ„±

for (Mountain m : range) 
m.climb() 

μ˜ˆμ™Έλ₯Ό μ¨μ„œ 루프λ₯Ό μ’…λ£Œν•œ μ΄μœ λŠ” λ¬΄μ—‡μΌκΉŒ?

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

μ˜ˆμ™Έλ₯Ό μ‚¬μš©ν•œ μͺ½μ΄ ν‘œμ€€ κ΄€μš©κ΅¬λ³΄λ‹€ 훨씬 λŠλ¦¬λ‹€. μ›μ†Œ 100개짜리 λ°°μ—΄λ‘œ ν…ŒμŠ€νŠΈν•΄λ³΄λ‹ˆ 2λ°° 정도 λŠ˜λ Έλ‹€. μ˜ˆμ™Έλ₯Ό μ‚¬μš©ν•œ 반볡문이 해악은 μ½”λ“œλ₯Ό ν—·κ°ˆλ¦¬κ²Œ ν•˜κ³  μ„±λŠ₯을 λ–¨μ–΄λœ¨λ¦¬λŠ”λ°μ„œ λλ‚˜μ§€ μ•ŠλŠ”λ‹€. 심지어 μ œλŒ€λ‘œ λ™μž‘ν•˜μ§€ μ•Šμ„ μˆ˜λ„ μžˆλ‹€.

  • 반볡문 μ•ˆμ— 버그가 μˆ¨μ–΄ μžˆλ‹€λ©΄ 흐름 μ œμ–΄μ— 쓰인 μ˜ˆμ™Έκ°€ 이 버그λ₯Ό 숨겨 디버깅을 훨씬 μ–΄λ ΅κ²Œ ν•  것이닀.

*** μ˜ˆμ‹œ 상황

  • 반볡문의 λͺΈμ²΄μ—μ„œ ν˜ΈμΆœν•œ λ©”μ„œλ“œκ°€ λ‚΄λΆ€μ—μ„œ κ΄€λ ¨ μ—†λŠ” 배열을 μ‚¬μš©ν•˜λ‹€κ°€ ArrayIndexOutOfBoundsException 을 μΌμœΌμΌ°λ‹€κ³  ν•΄λ³΄μž. ν‘œμ€€ κ΄€μš©κ΅¬ μ˜€λ‹€λ©΄ 이 λ²„κ·ΈλŠ” μ˜ˆμ™Έλ₯Ό μž‘μ§€ μ•Šκ³ (μŠ€νƒ μΆ”μ • 정보λ₯Ό 남기고) ν•΄λ‹Ή μŠ€λ ˆλ“œλ₯Ό 즉각 μ’…λ£Œμ‹œν‚¬ 것이닀.
  • 반면 μ˜ˆμ™Έλ₯Ό μ‚¬μš©ν•œ λ°˜λ³΅λ¬Έμ€ 버그 λ•Œλ¬Έμ— λ°œμƒν•œ μ—‰λš±ν•œ μ˜ˆμ™Έλ₯Ό 정상적인 반볡문 μ’…λ£Œ μƒν™©μœΌλ‘œ μ˜€ν•΄ν•˜κ³  λ„˜μ–΄κ°„λ‹€.

*** κ΅ν›ˆ

  • μ˜ˆμ™ΈλŠ” (κ·Έ 이름이 말해주듯) 였직 μ˜ˆμ™Έ μƒν™©μ—μ„œλ§Œ 써야 ν•œλ‹€. μ ˆλŒ€λ‘œ 일상적인 μ œμ–΄ νλ¦„μš©μœΌλ‘œ μ“°μ—¬μ„  μ•ˆ λœλ‹€.
  • 이 원칙은 API 섀계에도 μ μš©λœλ‹€. 잘 μ„€κ³„λœ API라면 ν΄λΌμ΄μ–ΈνŠΈκ°€ 정상적인 μ œμ–΄ νλ¦„μ—μ„œ μ˜ˆμ™Έλ₯Ό μ‚¬μš©ν•  일이 μ—†κ²Œ ν•΄μ•Ό ν•œλ‹€.
  • νŠΉμ • μƒνƒœμ—μ„œλ§Œ ν˜ΈμΆœν•  수 μžˆλŠ” 'μƒνƒœ 의쑴적' λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•˜λŠ” ν΄λž˜μŠ€λŠ” 'μƒνƒœ 검사' λ©”μ„œλ“œλ„ ν•¨κ»˜ μ œκ³΅ν•΄μ•Ό ν•œλ‹€.

Iterator μΈν„°νŽ˜μ΄μŠ€μ˜ next와 hasNextκ°€ 각각 μƒνƒœ 의쑴적 λ©”μ„œλ“œμ™€ μƒνƒœ 검사 λ©”μ„œλ“œμ— ν•΄λ‹Ήν•œλ‹€. λ³„λ„μ˜ μƒνƒœ 검사 λ©”μ„œλ“œ 덕뢄에 λ‹€μŒκ³Ό 같은 ν‘œμ€€ for κ΄€μš©κ΅¬λ₯Ό μ‚¬μš©ν•  μˆ˜λ„ μžˆλ‹€. (for-each도 λ‚΄λΆ€μ μœΌλ‘œ hasNextλ₯Ό μ‚¬μš©ν•œλ‹€.)

for (Iterator<Foo> i = collection.iterator(); i.hasNext();) {
   Foo foo = i.next();
} 

Iteratorκ°€ hasNextλ₯Ό μ œκ³΅ν•˜μ§€ μ•Šμ•˜λ‹€λ©΄ κ·Έ 일을 ν΄λΌμ΄μ–ΈνŠΈκ°€ λŒ€μ‹ ν•΄μ•Όλ§Œ ν–ˆλ‹€.

// μ»¬λ ‰μ…˜μ„ 이런 μ‹μœΌλ‘œ μˆœνšŒν•˜μ§€ 말 것 try {

Iterator i = collection.iterator(); While(true) { Foo foo = i.next(); } } catch (NoSuchElementException e) { }

λ°˜λ³΅λ¬Έμ— μ˜ˆμ™Έλ₯Ό μ‚¬μš©ν•˜λ©΄ μž₯ν™©ν•˜κ³  ν—·κ°ˆλ¦¬λ©° 속도도 느리고 μ—‰λš±ν•œ κ³³μ—μ„œ λ°œμƒν•œ 버그λ₯Ό μˆ¨κΈ°κΈ°λ„ ν•œλ‹€.

μƒνƒœ 검사 λ©”μ„œλ“œ, μ˜΅μ…”λ„, νŠΉμ • κ°’ 쀑 ν•˜λ‚˜λ₯Ό μ„ νƒν•˜λŠ” 지침

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