아이템 6. 불필요한 객체 생성을 피하라

같은 기능을 하는 객체를 여러 번 사용하는 것 보다 객체 하나를 재사용 하는 것이 더 나을 때가 있다.

String s1 = new String("java");
String s2 = new String("java");

System.out.println(s1 == s2); // false

String s3 = "java";
String s4 = "java";

System.out.println(s3 == s4); // true

s1, s2의 생성 방법은 java라는 문자열을 매번 새로 생성하지만,

s3, s4는 String Constant Pool을 사용하여 java라는 문자열을 캐싱하여 사용함

image.png

정적 팩터리 메서드

Wrapper Class에서는 캐싱을 지원해주는 valueOf()라는 메소드가 존재한다.

대표적으로 자주 사용하는 Boolean의 경우에는 true/false를,

Short, Integer와 Long의 경우에는 -128 ~ 127까지의 수의 캐싱을 지원해준다.

Integer i1 = new Integer(50);
Integer i2 = new Integer(50);

System.out.println(i1 == i2); // false

Integer i3 = Integer.valueOf(50);
Integer i4 = Integer.valueOf(50);

System.out.println(i3 == i4); // true

생성 비용이 비싼 객체

public class RomanNumerals {
    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 메소드를 사용하는 것임

정규 표현식으로 문자열 형태를 확인하는 가장 쉬운 방식이지만 성능이 중요한 상황에서는 반복해 사용하기엔 적합하지 않음.

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();
    }
}