HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🛁
공부기록
/
📚
책 정리
/
🛖
item6 - 불필요한 객체 생성을 피해라
🛖

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 // 불필요하게 오토박싱이 계속해서 일어난다. } }
  • 인스턴스를 그만큼 계속해서 만들기 때문에 단순해도 상당히 시간이 걸린다.
  • 따라서 박싱된 기본 타입보다는 기본 타입을 생성하고 의도치 않은 오토박싱이 숨어들지 않도록 주의하자.
즉 주의해야 할 점은 위의 세가지는 특수한 상황이다.
같은 오브젝트 / 불 필요하게 객체를 생성할 필요가 없으니 생성하지 말라는 뜻이다.
만드는데 무거운 객체들은 재사용 하는것을 권장하는 것이다.
불필요하게 많은 객체들을 만드는걸 조심하자 일반적인 경우에 객체를 만들지 말라는 소리는 절대 아니다 !