item 6 leekyunghee - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

λΆˆν•„μš”ν•œ 객체 생성을 ν”Όν•˜λΌ

λ˜‘κ°™μ€ κΈ°λŠ₯의 객체λ₯Ό 맀번 μƒμ„±ν•˜κΈ°λ³΄λ‹€λŠ” 객체 ν•˜λ‚˜λ₯Ό μž¬μ‚¬μš©ν•˜λŠ” 편이 λ‚˜μ„ λ•Œκ°€ λ§Žλ‹€.

  • 객체 ν•˜λ‚˜λ₯Ό μž¬μ‚¬μš©ν•˜λŠ” 것은 λΉ λ₯΄κ³  μ„Έλ ¨λ˜λ‹€.
  • 특히 λΆˆλ³€ 객체(μ•„μ΄ν…œ 17)λŠ” μ–Έμ œλ“  μž¬μ‚¬μš©ν•  μˆ˜μžˆλ‹€.

λΆˆλ³€ κ°μ²΄λŠ” 근본적으둜 μŠ€λ ˆλ“œ μ•ˆμ „ν•˜μ—¬ λ”°λ‘œ 동기화할 ν•„μš” μ—†λ‹€.

λΆˆλ³€ κ°μ²΄λŠ” μ•ˆμ‹¬ν•˜κ³  κ³΅μœ ν•  수 μžˆλ‹€.

String s = new String("bikini");     // 싀행될 λ•Œλ§ˆλ‹€ String μΈμŠ€ν„΄μŠ€λ₯Ό μƒˆλ‘œ λ§Œλ“ λ‹€. 
String s = "bikini";                 // ν•˜λ‚˜μ˜ String μΈμŠ€ν„΄μŠ€λ₯Ό μ‚¬μš©ν•œλ‹€. 

μƒμ„±μž λŒ€μ‹  정적 νŒ©ν† λ¦¬ λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•˜λŠ” λΆˆλ³€ ν΄λž˜μŠ€μ—μ„œλŠ” 정적 νŒ©ν† λ¦¬ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•΄ λΆˆν•„μš”ν•œ 객체 생성을 ν”Όν•  수 μžˆλ‹€.

  • Boolean(String) μƒμ„±μž λŒ€μ‹  Boolean.valueOf(String) νŒ©ν† λ¦¬ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 것이 μ’‹λ‹€.

이 μƒμ„±μžλŠ” μžλ°” 9μ—μ„œ deprecated

  • μƒμ„±μžλŠ” ν˜ΈμΆœν•  λ•Œλ§ˆλ‹€ μƒˆλ‘œμš΄ 객체λ₯Ό λ§Œλ“€μ§€λ§Œ, νŒ©ν† λ¦¬ λ©”μ„œλ“œλŠ” μ „ν˜€ 그렇지 μ•Šλ‹€.
  • λΆˆλ³€ 객체만이 μ•„λ‹ˆλΌ κ°€λ³€ 객체라 해도 μ‚¬μš© 쀑에 λ³€κ²½ λ˜μ§€ μ•Šμ„ κ²ƒμž„μ„ μ•ˆλ‹€λ©΄ μž¬μ‚¬μš©ν•  수 μžˆλ‹€.

μ •κ·œν‘œν˜„μ‹μ„ ν™œμš©ν•œ κ°€μž₯ μ‰¬μš΄ 해법

μ„±λŠ₯을 훨씬 더 λŒμ–΄μ˜¬λ¦΄ 수 μžˆλ‹€.

static boolean isRomanNumeral(String s) {
    return s.matches("^(?=.)M*(C[MD[|D?C{0,]})"
           + "(X[CL])|L?X{0,3})(I[XV]|V?I{0,3})$");
}
  • String.matchesλŠ” μ„±λŠ₯이 μ€‘μš”ν•œ μƒν™©μ—μ„œ λ°˜λ³΅ν•΄ μ‚¬μš©ν•˜κΈ°λŠ” μ ν•©ν•˜μ§€ μ•Šλ‹€.
  • 이 λ©”μ„œλ“œκ°€ λ§Œλ“œλŠ” μ •κ·œν‘œν˜„μ‹μš© Pattern μΈμŠ€ν„΄μŠ€λŠ” ν•œλ²ˆμ“°κ³  λ²„λ €μ Έμ„œ κ³§λ°”λ‘œ 가비지 μ»¬λ ‰μ…˜ λŒ€μƒμ΄ λœλ‹€.
  • Pattern은 μž…λ ₯받은 μ •κ·œν‘œν˜„μ‹μ— ν•΄λ‹Ήν•˜λŠ” μœ ν•œ μƒνƒœ 머신을 λ§Œλ“€κΈ° λ•Œλ¬Έμ— μΈμŠ€ν„΄μŠ€ 생성 λΉ„μš©μ΄ λ†’λ‹€.

κ°’λΉ„μ‹Ό 객체λ₯Ό μž¬μ‚¬μš©ν•΄ μ„±λŠ₯을 κ°œμ„ ν•œλ‹€.

μ„±λŠ₯을 κ°œμ„ ν•˜λ €λ©΄ ν•„μš”ν•œ μ •κ·œν‘œν˜„μ‹μ„ ν‘œν˜„ν•˜λŠ” (λΆˆλ³€μΈ) Pattern μΈμŠ€ν„΄μŠ€λ₯Ό 클래슀 μ΄ˆκΈ°ν™”(정적 μ΄ˆκΈ°ν™”) κ³Όμ •μ—μ„œ 직접 생성해 캐싱해두고 λ‚˜μ€‘μ— isRomanNumeral λ©”μ„œλ“œκ°€ 호좜될 λ•Œλ§ˆλ‹€ 이 μΈμŠ€ν„΄μŠ€λ₯Ό μž¬μ‚¬μš©ν•œλ‹€.

public class RomanNumerals {
    private static final Pattern ROMAN = Pattern.compile(
            "^(?=.)M*(C[MD[|D?C{0,3})"
           + "(X[CL])|L?X{0,3})(I[XV]|V?I{0,3})$");
    static boolean isRomanNumeral(String s) {
        return ROMAN.matcher(s).matches();
    }     
}
  • Pattern μΈμŠ€ν„΄μŠ€λ₯Ό static final ν•„λ“œλ‘œ 끄집어내고 이름을 지어주어 μ½”λ“œμ˜ μ˜λ―Έκ°€ 훨씬 잘 λ“œλŸ¬λ‚œλ‹€.
  • κ°œμ„ λœ isRomanNumeral λ°©μ‹μ˜ ν΄λž˜μŠ€κ°€ μ΄ˆκΈ°ν™”λœ ν›„ 이 λ©”μ„œλ“œλ₯Ό ν•œ λ²ˆλ„ ν˜ΈμΆœν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ ROMAN ν•„λ“œλŠ” 쓸데없이 μ΄ˆκΈ°ν™”λœ 꼴이닀.
  • isRomanNumeral λ©”μ„œλ“œκ°€ 처음 호좜될 λ•Œ ν•„λ“œλ₯Ό μ΄ˆκΈ°ν™”ν•˜λŠ” 지연 μ΄ˆκΈ°ν™” (μ•„μ΄ν…œ 83)둜 λΆˆν•„μš”ν•œ μ΄ˆκΈ°ν™”λ₯Ό 없앨 μˆ˜λŠ” μžˆμ§€λ§Œ ꢌμž₯ ν•˜μ§€ μ•ŠλŠ”λ‹€.
  • 지연 μ΄ˆκΈ°ν™”λŠ” μ½”λ“œλ₯Ό λ³΅μž‘ν•˜κ²Œ λ§Œλ“œλŠ”λ° μ„±λŠ₯을 크게 κ°œμ„ λ˜μ§€ μ•Šμ„ λ•Œκ°€ 많기 λ•Œλ¬Έμ΄λ‹€.

λΆˆν•„μš”ν•œ 객체λ₯Ό λ§Œλ“€μ–΄λ‚΄λŠ” μ˜ˆμ‹œ

객체가 λΆˆλ³€μ΄λΌλ©΄ μž¬μ‚¬μš©ν•΄λ„ μ•ˆμ „ν•¨μ΄ λͺ…λ°±ν•˜λ‹€.

  • Adapterλ₯Ό view라고도 ν•œλ‹€.
  • μ–΄λŒ‘ν„°λŠ” μ‹€μ œ μž‘μ—…μ€ 뒷단 객체에 μœ„μž„ν•˜κ³  μžμ‹ μ€ 제2의 μΈν„°νŽ˜μ΄μŠ€ 역할을 ν•΄μ£ΌλŠ” 객체닀. μ–΄λŒ‘ν„°λŠ” 뒷단 객체만 κ΄€λ¦¬ν•˜λ©΄ λœλ‹€.
  • 뒷단 객체 μ™Έμ—λŠ” 관리할 μƒνƒœκ°€ μ—†μœΌλ―€λ‘œ 뒷단 객체 ν•˜λ‚˜λ‹Ή μ–΄λŒ‘ν„° ν•˜λ‚˜μ”©λ§Œ λ§Œλ“€μ–΄μ§€λ©΄ μΆ©λΆ„ν•˜λ‹€.
  • Map μΈν„°νŽ˜μ΄μŠ€μ˜ keySet λ©”μ„œλ“œλŠ” Map 객체 μ•ˆμ˜ ν‚€ μ „λΆ€λ₯Ό 담은 Setλ·°λ₯Ό λ°˜ν™˜ν•œλ‹€.
  • keySet을 ν˜ΈμΆœν•  λ•Œλ§ˆλ‹€ μƒˆλ‘œμš΄ Set μΈμŠ€ν„΄μŠ€κ°€ λ§Œλ“€μ–΄μ§€λ¦¬λΌκ³  생각할 수 μžˆμ§€λ§Œ 사싀은 맀번 같은 Set μΈμŠ€ν„΄μŠ€λ₯Ό λ°˜ν™˜ν• μ§€λ„ λͺ¨λ₯Έλ‹€.
  • λ°˜ν™˜λœ Set μΈμŠ€ν„΄μŠ€κ°€ 일반적으둜 가변이더라도 λ°˜ν™˜λœ μΈμŠ€ν„΄μŠ€λ“€μ€ κΈ°λŠ₯적으둜 λͺ¨λ‘ λ˜‘κ°™λ‹€.
  • 즉 λ°˜ν™˜ν•œ 객체쀑 ν•˜λ‚˜λ₯Ό μˆ˜μ •ν•˜λ©΄ λ‹€λ₯Έ λͺ¨λ“  객체가 λ”°λΌμ„œ 바뀐닀. λͺ¨λ‘κ°€ λ˜‘κ°™μ€ Map μΈμŠ€ν„΄μŠ€λ₯Ό λŒ€λ³€ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.

μ˜€ν† λ°•μ‹±(auto boxing)

  • μ˜€ν† λ°•μ‹±μ€ κΈ°λ³Έ νƒ€μž…κ³Ό λ°•μ‹±λœ κΈ°λ³Έ νƒ€μž…μ„ μ„žμ–΄ μ“Έ λ•Œ μžλ™μœΌλ‘œ μƒν˜Έ λ³€ν™˜ν•΄μ£ΌλŠ” 기술
  • κΈ°λ³Έ νƒ€μž…κ³Ό 그에 λŒ€μ‘ν•˜λŠ” λ°•μ‹±λœ κΈ°λ³Έ νƒ€μž…μ˜ ꡬ뢄을 νλ €μ£Όμ§€λ§Œ μ™„μ „νžˆ μ—†μ• μ£ΌλŠ” 것은 μ•„λ‹ˆλ‹€.
  • 의미 μƒμœΌλ‘œλŠ” 별닀λ₯Ό 것 μ—†μ§€λ§Œ μ„±λŠ₯μ—μ„œλŠ” 그렇지 μ•Šλ‹€. (μ•„μ΄ν…œ 61)
// λͺ¨λ“  μ–‘μ˜ μ •μˆ˜μ˜ 총합 κ΅¬ν•˜κΈ°
// intλŠ” μΆ©λΆ„νžˆ 크지 μ•ŠμœΌλ‹ˆ long을 μ‚¬μš©
private static long sum() {
   Long sum = 0L;
   for(long i=0; i <= Integer.MAX_VALUE; i++_
      sum  += i;
   return sum;
}

sum λ³€μˆ˜λ₯Ό long이 μ•„λ‹Œ Long으둜 μ„ μ–Έν•΄μ„œ λΆˆν•„μš”ν•œ Long μΈμŠ€ν„΄μŠ€κ°€ μ•½ 231κ°œλ‚˜ λ§Œλ“€μ–΄μ§„ 것이닀.

λŒ€λž΅ long νƒ€μž…μΈ iκ°€ Long νƒ€μž…μΈ sum에 λ”ν•΄μ§ˆ λ•Œλ§ˆλ‹€).

λ‹¨μˆœνžˆ sum의 νƒ€μž…μ„ long으둜만 λ°”κΏ”μ£Όλ©΄ 속도가 빨라진닀. (6.3초 -> 0.59초둜)

  • λ°•μ‹±λœ κΈ°λ³Έ νƒ€μž… λ³΄λ‹€λŠ” κΈ°λ³Έ νƒ€μž…μ„ μ‚¬μš©ν•˜κ³  μ˜λ„μΉ˜ μ•Šμ€ μ˜€ν† λ°•μ‹±μ΄ μˆ¨μ–΄λ“€μ§€ μ•Šλ„λ‘ μ£Όμ˜ν•˜μž.

핡심 정리

κΈ°μ‘΄ 객체λ₯Ό μž¬μ‚¬μš© ν•΄μ•Ό ν•œλ‹€λ©΄ μƒˆλ‘œμš΄ 객체λ₯Ό λ§Œλ“€μ§€ 마라 
무거운 객체가 μ•„λ‹Œ λ‹¨μˆœνžˆ 객체 생성을 ν”Όν•˜κ³ μž 객체 ν’€(pool)을 λ§Œλ“€μ§€λŠ” 말자. 
DB Connection 같은 생성 λΉ„μš©μ΄ λΉ„μ‹Έλ‹ˆ μž¬μ‚¬μš©ν•˜λŠ” 편이 λ‚˜μœΌλ‚˜ 자체 객체 풀은 μ½”λ“œλ₯Ό ν—·κ°ˆλ¦¬κ²Œ λ§Œλ“€κ³  λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰μ„ 늘리고 μ„±λŠ₯을 λ–¨μ–΄λœ¨λ¦°λ‹€.  
  • μƒˆλ‘œμš΄ 객체λ₯Ό λ§Œλ“€μ–΄μ•Ό ν•œλ‹€λ©΄ κΈ°μ‘΄ 객체λ₯Ό μž¬μ‚¬μš©ν•˜μ§€ 마라 (item 50, 302page)
  • 방어적 볡사가 ν•„μš”ν•œ μƒν™©μ—μ„œ 객체λ₯Ό μž¬μ‚¬μš©ν–ˆμ„ λ•Œμ˜ ν”Όν•΄κ°€ ν•„μš” μ—†λŠ” 객체λ₯Ό 반볡 μƒμ„±ν–ˆμ„ λ•Œμ˜ 피해보닀 훨씬 크닀.