// 안좋은 예 - 호출될 때마다 인스턴스 새로 생성
String s = new String("bad example");
// 하나의 String 인스턴스 사용
String s = "good example";
자바는 문자열을 직접 할당할 시 문자열 상수 풀 내부에 모든 값을 저장
문자열 상수 풀은 힙 내에 있는 작은 캐시임
생성자는 매번 새로운 객체를 생성하지만, 팩토리 메서드는 그렇지 않으므로 new Boolean(String) 보다 Boolean.valuesOf(String) 팩토리 메서드를 사용하는 것이 좋음
또 다른 예시 : String.matches
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 boolean matches(String regex) {
return Pattern.matches(regex, this);
}
public static boolean matches(String regex, CharSequence input) {
Pattern p = Pattern.compile(regex):
Matcher m = p.matcher(input):
return m.matches();
}
String.matches 메서드 내부에서 만드는 정규표현식용 Pattern 인스턴스는 한번 쓰고 버려져 곧 바로 가비지 컬렉션 대상이 됨
Pattern
은 입력받은 정규표현식에 해당하는 유한 상태 머신(finite state machine)을 만들어 인스턴스 생성 비용이 높음<aside> 💡 finite state machine 이란
상태를 기반으로 동작하는 개념의 방식으로, 상태를 기반으로 처리되기 때문에 한 번에 한 개의 상태만 처리된다. 상태에 기반한 조건에 의해 처리되므로, 상태 값이 변경되면 상태에 대한 종료 및 다른 상태로의 변환을 처리한다.
</aside>
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();
}
}
public class Sum {
private static long sum() {
Long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++) {
sum += i;
}
return sum;
}
}