똑같은 기능의 객체는 반복적으로 생성할 이유가 없다. 본문에서는 다음과 예시 코드를 제시한다.
String s = new String("bikini");
String s = "bikini";
명시적으로 new
를 사용해서 문자열 객체를 만드는 행위는 무의미하며 성능에 악영향만 끼친다. 개선된 코드는 문자열 리터럴을 사용하며, 동일한 값에 대해 모든 객체가 똑같다는 사실이 보장된다.
리터럴이란? JLS 에서는 다음과 같이 설명한다.
A literal is the source code representation of a value of a primitive type (§4.2), the String type (§4.3.3), or the null type (§4.1).
public class Main {
public static void main(String[] args) {
String id = "taehongkim";
String id2 = new String("taehongkim");
String id3 = "taehongkim";
System.out.println(id.equals(id2)); // true
System.out.println(id == id2); // false
System.out.println(id == id3); // true
}
}
위 코드의 실행결과는 리터럴을 사용해서 얻을 수 있는 이득을 확실하게 보여준다. 문자열 비교에서 ==
연산자가 권장되지 않는 방법이지만, 메모리 주소 비교를 위해서 위와 같이 작성했다.
앞서 아이템 1에서 정적 팩터리 메서드에 대해 다뤘다. 정적 팩터리 메서드의 장점으로 매번 새로운 객체를 생성하지 않아도 된다는 점이 언급되었다. 이는 지금 다루는 아이템 6 - 불필요한 객체 생성을 피하라는 조언과 일맥상통한다.
@Deprecated(
since = "9"
)
public Boolean(boolean value) {
this.value = value;
}
Boolean
클래스는 정적 팩터리 메서드인 valueOf()
를 가지며, 덕분에 새로운 객체를 전혀 생성하지 않고 인스턴스를 재활용할 수 있다. 자바 9 이후로는 위 코드와 같이 Boolean
클래스의 생성자가 deprecated 되었다. 불필요한 객체 생성을 하지 않는 쪽으로 발전하는 것이다.
static boolean isRomanNumeral(String s) {
return s.matches("<regex>")
}
동일한 값을 가지는 객체가 반복적으로 생성되는 것과는 반대로, 값비싼 객체를 재활용하는 방법도 생각해볼 수 있다.
위 코드는 정규표현식을 사용해서 주어진 문자열이 매칭되는지 확인하는 예제 코드이다. 본문에 의하면 이 코드에서 매칭을 위해 사용되는 Pattern
객체는 한 번 사용되고 곧바로 가비지 컬렉션 대상이 된다.
동일한 패턴으로 여러 문자열을 매칭시켜야하는 상황에서 큰 성능 손해가 발생할 가능성이 존재한다. 따라서 Pattern
객체를 재사용할 가능하도록 상수로 꺼내는 방법을 제안하고 있다.
이후로 몇 가지 내용이 더 등장하지만, 아직은 자세히 짚어보지 않아도 될 내용이라고 생각한다.
불필요한 객체 생성을 어떻게 막을 수 있을까? 어떤 객체가 반복적으로 사용되는지 짚어보고, 불변 객체로 만들 수 있는지를 고려하여 객체 생성으로 발생하는 성능 손해를 개선할 수 있다.