πŸ›–

item6 - λΆˆν•„μš”ν•œ 객체 생성을 피해라

속성
2μž₯

λΆˆν•„μš”ν•œ 객체 생성을 피해라

λ¬Έμžμ—΄μ€ λ¦¬ν„°λŸ΄λ‘œ λ§Œλ“€μž

  • λ˜‘κ°™μ€ κΈ°λŠ₯의 객체λ₯Ό 맀번 μƒμ„±ν•˜λŠ”κ²ƒ 보닀 객체 ν•˜λ‚˜λ₯Ό μž¬μ‚¬μš© ν•˜λŠ” 편이 λ‚˜μ„λ•Œκ°€ λ§Žλ‹€.
  • μž¬μ‚¬μš©μ€ λΉ λ₯΄κ³  λΆˆλ³€κ°μ²΄λŠ” μ–Έμ œλ“  μž¬μ‚¬μš© 될 수 μžˆλ‹€.
String hello = new String("μ•ˆλ…•");
  • μœ„μ˜ 방법은 싀행될 λ•Œ λ§ˆλ‹€ String μΈμŠ€ν„΄μŠ€λ₯Ό μƒˆλ‘œ λ§Œλ“€κ²Œ λœλ‹€. String은 β€œλΆˆλ³€β€μ΄κΈ° λ•Œλ¬Έμ— μœ„ λ°©λ²•μœΌλ‘œ λ°˜λ³΅μ΄λΌλ„ 돌면 λ˜‘κ°™μ€ κΈ°λŠ₯을 ν•˜λŠ” λ¬Έμžμ—΄μ„ 수백 수천개λ₯Ό λ§Œλ“€κ²Œ 될 수 있게되며 μ ˆλŒ€ ν•΄μ„œλŠ” μ•ˆλ˜λŠ” 행동이닀.
String hello = "μ•ˆλ…•"
  • μœ„ λ°©λ²•μœΌλ‘œ μ‹€ν–‰ν•˜λ©΄ 가상머신 μ•ˆμ— λ˜‘κ°™μ€ λ¬Έμžμ—΄ λ¦¬ν„°λŸ΄μ„ μ‚¬μš©ν•˜λŠ” λͺ¨λ“  μ½”λ“œκ°€ 같은 객체λ₯Ό μž¬μ‚¬μš©ν•¨μ΄ 보μž₯λœλ‹€.
근데 String은 μ™œ λΆˆλ³€μΌκΉŒ?
λ°˜λŒ€λ‘œ String이 가변이면? 같은 μ°Έμ‘°λ₯Ό κ°€μ§€λŠ” 객체의 값을 λ³€κ²½ν•  수 있게 λœλ‹€. 이 말은 같은 μ°Έμ‘° & λ‹€λ₯Έ κ°’ μ΄λΌλŠ” 상황을 λ§Œλ“€ 수 있기 λ•Œλ¬Έμ— μž¬μ‚¬μš©μ΄ λΆˆκ°€λŠ₯ν•΄μ§„λ‹€. λ”°λΌμ„œ 객체 곡유λ₯Ό ν†΅ν•œ μž¬μ‚¬μš© λͺ©μ μΈ String Pool 을 μ‚¬μš©ν•  수 μ—†κ²Œ λœλ‹€.
λ˜ν•œ κ°€λ³€ μƒνƒœμ˜ κ°μ²΄λŠ” 같은 λ¬Έμžμ—΄ λ¦¬ν„°λŸ΄μ„ 가지더라도 객체λ₯Ό 맀번 생성해야 ν•œλ‹€. String이 많이 μ‚¬μš©λ˜λŠ” λ©”μ„œλ“œλ‚˜ λ°˜λ³΅λ¬Έμ—μ„œ μ“Έλ°μ—†λŠ” μΈμŠ€ν„΄μŠ€κ°€ 많이 λ§Œλ“€μ–΄μ§ˆ μˆ˜λ„ μžˆλ‹€λŠ” λœ»μ„ κ°€μ§€κ³  μžˆλ‹€. 즉 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ„±λŠ₯에 μ•ˆμ’‹μ€ 영ν–₯을 λ―ΈμΉœλ‹€.
for(int i=0; i<1000000; i++){ String str = new String("newString");}

μƒμ„±μž λŒ€μ‹  정적 νŒ©ν„°λ¦¬ λ©”μ†Œλ“œλ₯Ό μ΄μš©ν•΄ λΆˆν•„μš”ν•œ 객체 생성을 ν”Όν•  수 μžˆλ‹€.

notion image
 
Integer i = 100 // 1 Integer i = Integer.valueOf(100) // 2 // 3 private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7) assert IntegerCache.high >= 127; } private IntegerCache() {} }

λΉ„μ‹Ό 객체가 λ°˜λ³΅ν•΄μ„œ ν•„μš”ν•˜λ‹€λ©΄ μΊμ‹±ν•˜μ—¬ μž¬μ‚¬μš©ν•˜λΌ

import java.util.regex.Pattern; public class RomanNumerals { // 맀번 이 νŒ¨ν„΄μ„ μ μš©ν•˜λ©΄ λΉ„μš©λ„ λ§Žμ΄λ“€κ³  μˆ˜ν–‰ μ‹œκ°„λ„ λŠλ¦¬λ‹€. static boolean isRomanNumeralSlow(String s) { return s.matches("^(?=.)M*(C[MD]|D?C{0,3})" + "(X|CL|L?X{0,3})(I[XV]|V?I{0,3}$"); } // 객체λ₯Ό μž¬μ‚¬μš©ν•΄μ„œ μ„±λŠ₯을 올리자 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 isRomanNumeralFast(String s) { return ROMAN.matcher(s).matches(); } }

μ˜€ν† λ°•μ‹±μ„ μ‘°μ‹¬ν•˜μž

public static long sum() { Long sum = 0L; for (long i = 0; i <= Integer.MAX_VALUE; i++) { sum += i // λΆˆν•„μš”ν•˜κ²Œ μ˜€ν† λ°•μ‹±μ΄ κ³„μ†ν•΄μ„œ μΌμ–΄λ‚œλ‹€. } }
  • μΈμŠ€ν„΄μŠ€λ₯Ό 그만큼 κ³„μ†ν•΄μ„œ λ§Œλ“€κΈ° λ•Œλ¬Έμ— λ‹¨μˆœν•΄λ„ μƒλ‹Ήνžˆ μ‹œκ°„μ΄ κ±Έλ¦°λ‹€.
  • λ”°λΌμ„œ λ°•μ‹±λœ κΈ°λ³Έ νƒ€μž…λ³΄λ‹€λŠ” κΈ°λ³Έ νƒ€μž…μ„ μƒμ„±ν•˜κ³  μ˜λ„μΉ˜ μ•Šμ€ μ˜€ν† λ°•μ‹±μ΄ μˆ¨μ–΄λ“€μ§€ μ•Šλ„λ‘ μ£Όμ˜ν•˜μž.
즉 μ£Όμ˜ν•΄μ•Ό ν•  점은 μœ„μ˜ μ„Έκ°€μ§€λŠ” νŠΉμˆ˜ν•œ 상황이닀.
같은 였브젝트 / 뢈 ν•„μš”ν•˜κ²Œ 객체λ₯Ό 생성할 ν•„μš”κ°€ μ—†μœΌλ‹ˆ μƒμ„±ν•˜μ§€ λ§λΌλŠ” λœ»μ΄λ‹€.
λ§Œλ“œλŠ”λ° 무거운 객체듀은 μž¬μ‚¬μš© ν•˜λŠ”κ²ƒμ„ ꢌμž₯ν•˜λŠ” 것이닀.
λΆˆν•„μš”ν•˜κ²Œ λ§Žμ€ 객체듀을 λ§Œλ“œλŠ”κ±Έ μ‘°μ‹¬ν•˜μž 일반적인 κ²½μš°μ— 객체λ₯Ό λ§Œλ“€μ§€ λ§λΌλŠ” μ†Œλ¦¬λŠ” μ ˆλŒ€ μ•„λ‹ˆλ‹€ !