불필요한 객체 생성을 피하라
똑같은 기능의 객체를 매번 생성해서 사용하기보다는 객체 하나를 재사용 하는 편이 나을때가 많다.
재사용은 빠르고 편하며, 불편 객체는 언제 재사용 할 수 있다.
String s = new String("bikini");
String s = "bikini";
위 두 코드는 문자열 bikini를 String 타입 s에 저장하지만 동작 방식이 다르다.
첫번째 코드는 매번 새로운 인스턴스를 Heap에 생성하여 변수에 할당하지만, 두번째 코드는 "bikini"라는 문자열이 처음 나왔을때만 Heap영역 string pool에 저장하고 리터럴 "bikini"를 사용하는 모든곳에서 공유되어 같은 객체를 재사용함이 보장된다.
값이 비싼 객체는 캐싱해두어 사용하기
객체중 생성 비용이 아주 비싼 객체도 더러 있다.
이런 비싼 객체가 반복해서 필요하다면 캐싱하여 재사용하는게 좋다.
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.matchs는 정규표현식으로 문자열 형태를 확인하는 가장 쉽고 편리한 방법이지만 성능이 중요한 상황에서 반복해 사용기에는 적합하지 않다. 이 메서드에는 호출될때마다 정규 표현식용 Pattern 인스턴스를 생성하고 사용 후 버려 가비지 컬렉션 대상이 된다.
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 인스턴스를 클래스 생성 과정에서 직접 캐싱해두고 호출할때마다 캐싱된 인스턴스를 재사용하면된다.
박싱 타입 사용시 주의할 점
private static long sum() {
Long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++)
sum += i;
return sum;
}
해당 코드를 보면 sum 변수는 Long이라는 박싱타입을 사용하고 i는 long 타입이다.
불필요한 박싱 타입을 사용하여 i값을 sum에 더할때마다 오토박싱이 발생해 프로그램을 느리게 만든다.
이러한 문제를 해결하기 위해서는 박싱된 타입보단 기본타입을 사용함, 의도치 않은 오토박싱이 숨어들지 않도록 주의 해야한다.
위 사례들을 보면 객체 생성은 비싸니 피해야 한다로 오해하면 안된다.
요즘의 JVM에서는 별 다른 일을 하지 않는 작은 객체를 생성하고 회수하는 일이 크게 부담되지는 않는다.
프로그램 명확성, 간결성, 기능을 위해 객체를 추가로 생성 하는것이라면 일반적으로 좋은일이다.
'book review > Effective java' 카테고리의 다른 글
[Effective Java] Item 8. finalizer와 cleaner 사용을 피하라 (0) | 2024.02.13 |
---|---|
[Effective Java] Item 7. 다 쓴 객체 참조를 해제하라 (1) | 2024.02.07 |
[Effective Java] Item 5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라. (0) | 2024.02.05 |
[Effective Java] Item 4. 인스턴스화를 막으려거든 private 생성자를 사용하라 (0) | 2024.02.02 |
[Effective Java] Item 3. 생성자나 열거 타입으로 싱글턴임을 보증하라 (1) | 2024.02.01 |