## jdk1.5에서 String 더하기의 컴파일시의 최적화] String 클래스를 "+"로 반복해서 더하는 연산을 어떤 경우에 컴파일러에서 자동으로 최적화해주는지 알고 있다면 보다 융퉁성 있게 쓸 수가 있습니다. 몇년전에 javaservice.net에서의 [String vs StringBuffer에 대한 논의](http://www.javaservice.net/~java/bbs/read.cgi?m=qna&b=discussion&c=r_p&n=1053403354 "String vs StringBuffer에 대한 논의")에서도 이 이야기가 오고 갔었고, 그를 통해 제가 알게 되었던 바는 다음과 같습니다. 1. 한줄에서 상수 String끼리만 더하는 것은 모두 합쳐진 문자열로 바꿔준다. 즉 String a= "a" + "b" + "c"; 라고 쓰면 String ="abc"; 로 알아서 컴파일해준다는 거죠. 2. 한줄에서 상수와 다른 String 클래스를 더하는 것은 StringBuffer의 append, toString 메서드를 쓰는 코드로 준다. jdk 1.4 javadoc 의 [StringBuffer API설명](http://java.sun.com/j2se/1.4.2/docs/api/java/lang/StringBuffer.html "StringBuffer API설명") 에 명시되어 있네요. > String buffers are used by the compiler to implement the binary string concatenation operator . For example, the code: > x = "a" + 4 + "c" > is compiled to the equivalent of: > x = new StringBuffer().append("a").append(4).append("c").toString() > which creates a new string buffer (initially empty), appends the string representation of each operand to the string buffer in turn, and then converts the contents of the string buffer to a string. Overall, this avoids creating many temporary strings. Java 1.5 이상에서는 String더하기가 StringBuilder로 치환된다는 것을 듣고나서, 이것을 직접 테스트 해보았습니다. jdk1.5의 API문서를 보시면 아시겠지만 [StringBuilder](http://java.sun.com/j2se/1.5.0/docs/api/java/lang/StringBuilder.html "StringBuilder")는 동기화되지 않았다는 것이 [SringBuffer](http://java.sun.com/j2se/1.5.0/docs/api/java/lang/StringBuffer.html "SringBuffer")와 차이점입니다. 참고로 컴파일은 이클립스에서 한 후 [jad](http://www.kpdus.com/jad.html "jad")로 다시 역컴파일한 결과입니다. ### 원래 소스 ```java public class StringTest { public static void main(String[] args) { String str0 = "It's a string...."; String str1 = "It's" + " a string" + "...."; String str2 = "It's a string...." + str0 + "000"; str2 = str0 + str1 + "1111" ; str2 = str2 + "1111"; str2 += "1111"; for (int i=0;i<10;i++){ str2 = str2 + "1111"; str2 += "1111"; } } } ``` ### jdk 1.4로 compile ```java public class StringTest{ public StringTest() { } public static void main(String args[]) { String str0 = "It's a string...."; String str1 = "It's a string...."; String str2 = "It's a string...." + str0 + "000"; str2 = str0 + str1 + "1111"; str2 = str2 + "1111"; str2 = str2 + "1111"; for(int i = 0; i < 10; i++) { str2 = str2 + "1111"; str2 = str2 + "1111"; } } } ``` ### JDK 1.5로 compile ```java public class StringTest{ public StringTest() { } public static void main(String args[]) { String str0 = "It's a string...."; String str1 = "It's a string...."; String str2 = (new StringBuilder("It's a string....")).append(str0).append("000").toString(); str2 = (new StringBuilder(String.valueOf(str0))).append(str1).append("1111").toString(); str2 = (new StringBuilder(String.valueOf(str2))).append("1111").toString(); str2 = (new StringBuilder(String.valueOf(str2))).append("1111").toString(); for(int i = 0; i < 10; i++) { str2 = (new StringBuilder(String.valueOf(str2))).append("1111").toString(); str2 = (new StringBuilder(String.valueOf(str2))).append("1111").toString(); } } } ``` 상수 더하기는 역시 String str1 = "It's" + " a string" + "...."; -> String str1 = "It's a string...."; 으로 양 버전 모두에서 바뀝니다. 상수와 상수가 아닌 것을 섞어서 더했는 때는 jdk1.4로 이클립스에서 컴파일한 결과로는 StringBuffer가 나타나지는 않네요. 그리고 1.5에서는 예상대로 StringBuilder가 나타납니다. jdk1.4에서 StringBuffer로 자동치환이 안되어서 나오는 것은 좀 이상하기는 해도, 반복문이 아닌 곳에서 스트링 한두개를 더하는 정도라면 최적화해 주지 않아도 한 두개의 객체가 더 생기는 정도일 것이니까 큰 성능의 차이는 없을 것 같습니다. 1.5에서는 반복문 안에서의 더하기도 StringBuilder로 바꿔주기는 하지만 매루프마다 새로운 StringBuilder 클래스를 생성하는 것이므로 String과 마찬가지로 필요없는 임시객체를 계속 만들게 됩니다. 즉 어떤 경우라도 반복문안에서 String 더하기에 "+"를 쓰지는 말아야 겠죠.