String s1 = new String("this is String");
String s2 = "this is String";
s1
, s2
의 각기 다른 생성 방법입니다. 하지만 s1에 사용되는 방식은 스트링 객체를 생성하는데 있어 가장 나쁜 코드라고 할 수 있습니다. 왜 일까요?s2
와 같은 방식입니다. 해당 방식은 하나의 String Instance를 생성하며 해당 문자열 값을 가지는 모든 코드가 동일한 Instance를 사용합니다.
객체 생성자(constructor)를 사용하면 객체가 존재하는지 상관없이 매번 새로운 객체 인스턴스를 만들어 반환합니다. 앞에서 보셨듯이, 이는 자칫 성능에 좋지 못한 영향을 끼칠 수 있습니다.
그렇다면 객체가 존재한다면 해당 객체를 반환하게 하고, 존재하지 않는다면 새로운 객체 인스턴스를 반환하도록 어떻게 할 수 있을까요?
정답은 이전에 배웠던 정적 팩토리 메서드를 활용하는 것입니다.
String str = "TRUE";
Boolean b1 = new Boolean(str); // 생성자(constructor)를 사용한 객체 인스턴스 생성
Boolean b2 = Boolean.valueOf(str); // 정적 팩토리 메서드를 사용한 객체 인스턴스 재사용
b2
의 valueOf(str)
을 뜯어보면 다음과 같은 코드가 나옵니다.
/**
* The {@code Boolean} object corresponding to the primitive
* value {@code true}.
*/
public static final Boolean TRUE = new Boolean(true);
/**
* The {@code Boolean} object corresponding to the primitive
* value {@code false}.
*/
public static final Boolean FALSE = new Boolean(false);
public static boolean parseBoolean(String s) {
return "true".equalsIgnoreCase(s);
}
public static Boolean valueOf(String s) { // valueOf
return parseBoolean(s) ? TRUE : FALSE;
}
TRUE
, FALSE
객체가 이미 static final
로 선언되어 있습니다. 따라서 이 두 객체들은 프로그램이 실행되고 Boolean
객체를 사용하려고 할 때 이미 인스턴스가 생성되어 있습니다.
valueOf()
메서드는 입력으로 받은 String 값의 대소문자를 무시하고 true
와 비교하여 동일하다면 TRUE
객체를, 그렇지 않다면 FALSE
객체를 반환합니다.
Boolean
은 이미 만들어진 TRUE
, FALSE
객체를 재사용하고 있습니다.이런 객체의 재사용은 일반적으로 불변 객체를 대상으로 많이 적용됩니다. 하지만 가변 객체라 해도 해당 객체를 사용 중에 변경이 되지 않는다는 것을 인지하고 있다면, 재사용이 가능합니다.