자바 프로그램이 실행되는 동안 가장 많이 생성되는 객체
String string = new String("abc");
로 사용하지 말 것(객체 생성 비용 발생)
String string = "abc";
로 사용한다. 이 경우도 처음 호출된 경우 생성되지만 Java Heap안에 String Pool이라는 곳에 생성되어 후에 똑같은 값을 호출하는 경우 String Pool에서 가져다 쓴다. 반면에 new String으로 생성하는 경우 똑같은 값을 가지더라도 매번 새로 생성한다.
문자열 연산시 +
를 써도 바이트코드를 보면 builder를 생성하는 것을 볼 수 있다.(자바 버전 마다 다를 수 있음)
StringBuilder와 StringBuffer는 String과 달리 가변이다. 즉 append(), delete()등을 사용하면 동일 객체 내에서 값이 달라진다.(String은 연산시 새로운 객체를 생성한다.)
즉, 문자열 추가, 삭제, 수정이 자주 발생한다면 String대신 StringBuilder와 StringBuffer를 사용하는 것을 권장한다.
StringBuilder와 StringBuffer도 차이점이 있다. StringBuffer는 동기화를 지원하여 멀티쓰레드 환경에서 안전하고, StringBuilder는 동기화를 지원하지 않으므로 멀티쓰레드 환경에서 사용하는 것은 추천하지 않지만 단일 쓰레드에서는 StringBuffer보다 성능이 더 뛰어나다.
로컬 변수에 final 붙이면 최적화 될 수 있다.
1)
@Test
void StringFinalTest() {
String a = "a";
String b = "b";
System.out.println(a + b);
}
// .class
@Test
void StringFinalTest() {
String a = "a";
String b = "b";
System.out.println(a + b);
}
2)
@Test
void StringFinalTest() {
final String a = "a";
final String b = "b";
System.out.println(a + b);
}
// .class
@Test
void StringFinalTest() {
String a = "a";
String b = "b";
System.out.println("ab");
}
1)의 경우는 final을 붙이지 않고 String을 +
연산 했을 때의 클래스 파일이고 2)의 경우는 final을 붙인 상태에서 +
연산 했을 때의 클래스 파일이다.
1)의 경우는 a가 참조하는 값이 달라질 수 있기 때문에 클래스파일로 변환 된 상태에도 +가 남아있지만 2)의 경우는 final로 인해 참조하는 값이 불변임을 알기 때문에 바로 합쳐져있는 것을 볼 수 있다.