Skip to content

Instantly share code, notes, and snippets.

@benelog
Last active April 14, 2023 13:42
Show Gist options
  • Select an option

  • Save benelog/b81b4434fb8f2220cd0e900be1634753 to your computer and use it in GitHub Desktop.

Select an option

Save benelog/b81b4434fb8f2220cd0e900be1634753 to your computer and use it in GitHub Desktop.

Revisions

  1. benelog revised this gist Oct 25, 2016. 1 changed file with 57 additions and 54 deletions.
    111 changes: 57 additions & 54 deletions java-string-concat.md
    Original file line number Diff line number Diff line change
    @@ -17,64 +17,67 @@

    참고로 컴파일은 이클립스에서 한 후 [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";
    }
    }
    }
    ```

    > 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.4로 compile
    }
    }
    ```

    > 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() {
    }

    #### JDK 1.5로 compile

    > 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();
    > }
    > }
    > }
    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로 자동치환이 안되어서 나오는 것은 좀 이상하기는 해도, 반복문이 아닌 곳에서 스트링 한두개를 더하는 정도라면 최적화해 주지 않아도 한 두개의 객체가 더 생기는 정도일 것이니까 큰 성능의 차이는 없을 것 같습니다.

  2. benelog created this gist Oct 25, 2016.
    81 changes: 81 additions & 0 deletions java-string-concat.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,81 @@
    ## 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문서를 보시면 아시겠지만 [<span style="COLOR: #800080;">StringBuilder</span>](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")로 다시 역컴파일한 결과입니다.

    #### 원래 소스

    > 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

    > 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

    > 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 더하기에 "+"를 쓰지는 말아야 겠죠.