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

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

  • λ˜‘κ°™μ€ κΈ°λŠ₯의 객체λ₯Ό 맀번 μƒμ„±ν•˜κΈ°λ³΄λ‹€λŠ” 객체 ν•˜λ‚˜λ₯Ό μž¬μ‚¬μš©ν•˜λŠ” 편이 λ‚˜μ„ λ•Œκ°€ λ§Žλ‹€. μž¬μ‚¬μš©μ€ λΉ λ₯΄κ³  μ„Έλ ¨λ˜λ‹€. 특히 λΆˆλ³€ κ°μ²΄λŠ” μ–Έμ œλ“  μž¬μ‚¬μš©ν•  수 μžˆλ‹€.

new String("bikini") // λ”°λΌν•˜μ§€ 말 것!

  • 'new String("bikini")' λŠ” μ‹€ν–‰λ λ•Œ λ§ˆλ‹€ String μΈμŠ€ν„΄μŠ€λ₯Ό μƒˆλ‘œ λ§Œλ“ λ‹€. 이 λ¬Έμž₯에 λ°˜λ³΅λ¬Έμ΄λ‚˜ 빈번히 ν˜ΈμΆœλ˜λŠ” λ©”μ„œλ“œ μ•ˆμ— μžˆλ‹€λ©΄ μ“Έλ°μ—†λŠ” String μΈμŠ€ν„΄μŠ€κ°€ 수백만 개 λ§Œλ“€μ–΄μ§ˆ μˆ˜λ„ μžˆλ‹€.
String s = "bikini";
  • 이 μ½”λ“œλŠ” μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€λ₯Ό 맀번 λ§Œλ“œλŠ” λŒ€μ‹  ν•˜λ‚˜μ˜ String μΈμŠ€ν„΄μŠ€λ₯Ό μ‚¬μš©ν•œλ‹€. λ‚˜μ•„κ°€ 이 방식을 μ‚¬μš©ν•œλ‹€λ©΄ 같은 가상 λ¨Έμ‹  μ•ˆμ—μ„œ 이와 λ˜‘κ°™μ€ λ¬Έμžμ—΄ λ¦¬ν„°λŸ΄μ„ μ‚¬μš©ν•˜λŠ” λͺ¨λ“  μ½”λ“œκ°€ 같은 객체λ₯Ό μž¬μ‚¬μš©ν•¨μ΄ 보μž₯λœλ‹€.

new Boolean(String) // λ”°λΌν•˜μ§€ 말 것!

  • 'new Boolean(String)' λŠ” μžλ°”9μ—μ„œ deprecated API둜 μ§€μ •λ˜μ—ˆλ‹€. 'Boolean.valueOf(String)' λ₯Ό μ“°λŠ” 것이 μ’‹λ‹€.
  • μƒμ„±μž λŒ€μ‹  정적 νŒ©ν„°λ¦¬ λ§€μ„œλ“œ(μ•„μ΄ν…œ 1)λ₯Ό μ œκ³΅ν•˜λŠ” λΆˆλ³€ ν΄λž˜μŠ€μ—μ„œλŠ” 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•΄ λΆˆν•„μš”ν•œ 객체 생성을 ν”Όν•  수 μžˆλ‹€.

생성 λΉ„μš©μ΄ λΉ„μ‹Ό 객체

static boolean isRomanNumeral(String s){
    return s.matches("^(?=.)M*(C[MD]|D?C{0,3})"
    +"(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
}   
  • 이 λ°©μ‹μ˜ λ¬Έμ œλŠ” String.matches λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•œλ‹€λŠ” 데 μžˆλ‹€. String.matchesλŠ” μ •κ·œν‘œν˜„μ‹μœΌλ‘œ λ¬Έμžμ—΄ ν˜•νƒœλ₯Ό ν™•μΈν•˜λŠ” κ°€μž₯ μ‰¬μš΄ λ°©λ²•μ΄μ§€λ§Œ, μ„±λŠ₯이 μ€‘μš”ν•œ μƒν™©μ—μ„œ λ°˜λ³΅ν•΄ μ‚¬μš©ν•˜κΈ°μ—” μ ν•©ν•˜μ§€ μ•Šλ‹€.
  • 이 λ©”μ„œλ“œκ°€ λ‚΄λΆ€μ—μ„œ λ§Œλ“œλŠ” μ •κ·œν‘œν˜„μ‹μš© Pattern μΈμŠ€ν„΄μŠ€λŠ”, ν•œ 번 μ“°κ³  λ²„λ €μ Έμ„œ κ³§λ°”λ‘œ 가비지 μ»¬λ ‰μ…˜ λŒ€μƒμ΄ λœλ‹€.
  • Pattern은 μž…λ ₯받은 μ •κ·œν‘œν˜„μ‹μ— ν•΄λ‹Ήν•˜λŠ” μœ ν•œ μƒνƒœ λ¨Έμ‹ (finite state machine)을 λ§Œλ“€κΈ° λ•Œλ¬Έμ— μΈμŠ€ν„΄μŠ€ 생성 λΉ„μš©μ΄ λ†’λ‹€.
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 μΈμŠ€ν„΄μŠ€λ₯Ό 클래슀 μ΄ˆκΈ°ν™”(정적 μ΄ˆκΈ°ν™”) κ³Όμ •μ—μ„œ 직접 생성해 캐싱해두고, λ‚˜μ€‘μ— isRomanNumeral λ©”μ„œλ“œκ°€ 호좜될 λ•Œλ§ˆλ‹€ 이 μΈμŠ€ν„΄μŠ€λ₯Ό μž¬μ‚¬μš©ν•œλ‹€.

μ˜€ν†  λ°•μ‹±

  • μ˜€ν† λ°•μ‹±μ€ ν”„λ‘œκ·Έλž˜λ¨Έκ°€ κΈ°λ³Έ νƒ€μž…κ³Ό λ°•μ‹±λœ κΈ°λ³Έ νƒ€μž…μ„ μ„žμ–΄ μ“Έ λ•Œ μžλ™μœΌλ‘œ μƒν˜Έ λ³€ν™˜ν•΄μ£ΌλŠ” κΈ°μˆ μ΄λ‹€. μ˜€ν† λ°•μ‹±μ€ κΈ°λ³Έ νƒ€μž…κ³Ό 그에 λŒ€μ‘ν•˜λŠ” λ°•μ‹±λœ κΈ°λ³Έ νƒ€μž…μ˜ ꡬ뢄을 νλ €μ£Όμ§€λ§Œ, μ™„μ „νžˆ μ—†μ• μ£ΌλŠ” 것은 μ•„λ‹ˆλ‹€. μ˜λ―ΈμƒμœΌλ‘œλŠ” 별닀λ₯Ό 것 μ—†μ§€λ§Œ μ„±λŠ₯μ—μ„œλŠ” 그렇지 μ•Šλ‹€.
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에 λ”ν•΄μ§ˆ λ•Œλ§ˆλ‹€)
  • λ°•μ‹±λœ κΈ°λ³Έ νƒ€μž…λ³΄λ‹€λŠ” κΈ°λ³Έ νƒ€μž…μ„ μ‚¬μš©ν•˜κ³ , μ˜λ„μΉ˜ μ•Šμ€ μ˜€ν† λ°•μ‹±μ΄ μˆ¨μ–΄λ“€μ§€ μ•Šλ„λ‘ μ£Όμ˜ν•˜μž.

마무리

  • 이번 μ•„μ΄ν…œμ„ β€œκ°μ²΄ 생성은 λΉ„μ‹Έλ‹ˆ ν”Όν•΄μ•Ό ν•œλ‹€β€λ‘œ μ˜€ν•΄ν•˜λ©΄ μ•ˆ λœλ‹€. νŠΉνžˆλ‚˜ μš”μ¦˜μ˜ JVMμ—μ„œλŠ” 별닀λ₯Έ 일을 ν•˜μ§€ μ•ŠλŠ” μž‘μ€ 객체λ₯Ό μƒμ„±ν•˜κ³  νšŒμˆ˜ν•˜λŠ” 일이 크게 λΆ€λ‹΄λ˜μ§€ μ•ŠλŠ”λ‹€. ν”„λ‘œκ·Έλž¨μ˜ λͺ…ν™•μ„±, κ°„κ²°μ„±, κΈ°λŠ₯을 μœ„ν•΄μ„œ 객체λ₯Ό μΆ”κ°€λ‘œ μƒμ„±ν•˜λŠ” 것이라면 일반적으둜 쒋은 일이닀.

  • 거꾸둜, μ•„μ£Ό 무거운 객체가 μ•„λ‹Œ λ‹€μŒμ—μ•Ό λ‹¨μˆœνžˆ 객체 생성을 ν”Όν•˜κ³ μž μ—¬λŸ¬λΆ„λ§Œμ˜ 객체 ν’€(pool)을 λ§Œλ“€μ§€λŠ” 말자. λ¬Όλ‘  객체 풀을 λ§Œλ“œλŠ” 게 λ‚˜μ€ μ˜ˆκ°€ 있긴 ν•˜λ‹€. λ°μ΄ν„°λ² μ΄μŠ€ μ—°κ²° 같은 경우 생성 λΉ„μš©μ΄ μ›Œλ‚™ λΉ„μ‹Έλ‹ˆ μž¬μ‚¬μš©ν•˜λŠ” 편이 λ‚«λ‹€. ν•˜μ§€λ§Œ μΌλ°˜μ μœΌλ‘œλŠ” 자체 객체 풀은 μ½”λ“œλ₯Ό ν—·κ°ˆλ¦¬κ²Œ λ§Œλ“€κ³  λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰μ„ 늘리고 μ„±λŠ₯을 λ–¨μ–΄λœ¨λ¦°λ‹€. μš”μ¦˜ JVM의 가비지 μ»¬λ ‰ν„°λŠ” μƒλ‹Ήνžˆ 잘 μ΅œμ ν™”λ˜μ–΄μ„œ κ°€λ²Όμš΄ κ°μ²΄μš©μ„ λ‹€λ£° λ•ŒλŠ” 직접 λ§Œλ“  객체 풀보닀 훨씬 λΉ λ₯΄λ‹€.

  • 이번 μ•„μ΄ν…œμ€ 방어적 볡사(defensive copy)λ₯Ό λ‹€λ£¨λŠ” μ•„μ΄ν…œ 50κ³Ό λŒ€μ‘°μ μ΄λ‹€. 이번 μ•„μ΄ν…œμ΄ β€œκΈ°μ‘΄ 객체λ₯Ό μž¬μ‚¬μš©ν•΄μ•Ό ν•œλ‹€λ©΄ μƒˆλ‘œμš΄ 객체λ₯Ό λ§Œλ“€μ§€ λ§ˆλΌβ€λΌλ©΄, μ•„μ΄ν…œ 50은 β€œμƒˆλ‘œμš΄ 객체λ₯Ό λ§Œλ“€μ–΄μ•Ό ν•œλ‹€λ©΄ κΈ°μ‘΄ 객체λ₯Ό μž¬μ‚¬μš©ν•˜μ§€ λ§ˆλΌβ€λ‹€. 방어적 볡사가 ν•„μš”ν•œ μƒν™©μ—μ„œ 객체λ₯Ό μž¬μ‚¬μš©ν–ˆμ„ λ•Œμ˜ ν”Όν•΄κ°€, ν•„μš” μ—†λŠ” 객체λ₯Ό 반볡 μƒμ„±ν–ˆμ„ λ•Œμ˜ 피해보닀 훨씬 ν¬λ‹€λŠ” 사싀을 κΈ°μ–΅ν•˜μž.

  • 방어적 볡사에 μ‹€νŒ¨ν•˜λ©΄ μ–Έμ œ ν„°μ Έ λ‚˜μ˜¬μ§€ λͺ¨λ₯΄λŠ” 버그와 λ³΄μ•ˆ ꡬ멍으둜 μ΄μ–΄μ§€μ§€λ§Œ, λΆˆν•„μš”ν•œ 객체 생성은 κ·Έμ € μ½”λ“œ ν˜•νƒœμ™€ μ„±λŠ₯μ—λ§Œ 영ν–₯을 μ€€λ‹€.

끝