티스토리 뷰

반응형

JDK 1.5 버전 이후부터, String+ 연산은 컴파일시에 StringBuilder를 사용하도록 자동변환되어 성능 최적화가 이뤄진다고 알려져 있습니다. 그러나 String은 항상 StringBuilder로 변환되지 않습니다.

 

String 연산을 수행하는 몇가지의 예제를 준비했습니다. String을 연산하는 소스코드를 컴파일하고, 다시 디컴파일하여 성능최적화가 이뤄졌는지 확인해보겠습니다. (디컴파일러는 JAD를 사용하였으며, 예제코드들은 "012"라는 문자열을 이어붙여서 만드는 작업을 수행합니다.)

예제1) 한줄로 모두 선언한 경우

//컴파일 전 소스파일
String str1 = "0" + "1" + "2";
//컴파일 이 후, 디컴파일 한 소스파일
String str1 = "012";

한줄로 모두 선언한 경우는 하나의 String으로 변환 되었습니다. 결론적으로 성능최적화가 되었습니다. 따라서 이런 경우에 굳이 StringBuilder나 StringBuffer를 사용할 필요가 없습니다.

 

예제2) 여러줄로 선언한 경우

//컴파일 전 소스파일
String str2 = "";
    str2 += 0;
    str2 += 1;
    str2 += 2;
//컴파일 이 후, 디컴파일 한 소스파일
String str2 = "";
    str2 = (new StringBuilder()).append(s1).append("0").toString();
    str2 = (new StringBuilder()).append(s1).append("1").toString();
    str2 = (new StringBuilder()).append(s1).append("2").toString();

String 연산을 여러줄에 걸처 선언한 경우는 매 연산시마다 새로운 StringBuilder를 선언하고 있습니다. (StringBuilder를 사용하더라도) 매 연산시마다 새로운 객체를 생성하고 있으니 성능저하가 발생하게 됩니다. 따라서 이런 경우에는 StringBuilder 혹은 StringBuffer를 사용하여 성능최적화를 해야합니다.

 

예제3) 반복문 안에서 선언한 경우

//컴파일 전 소스파일
String str3 = "";
for (int i = 0; i < 3; i++) {
    str3 += i;
}
//컴파일 이 후, 디컴파일 한 소스파일
String str3 = "";
for(int i = 0; i < 3; i++) {
    str3 = (new StringBuilder()).append(s2).append(i).toString();
}

반복문안에서 연산을 수행하는 경우도 반복수행시마다 새로운 StringBuilder를 생성하고 있으니 성능저하가 발생하게 됩니다. 따라서 이런 경우에는 StringBuilder 혹은 StringBuffer를 사용하여 성능최적화를 해야합니다.

예제4) String의 concat() 메서드를 사용하여 선언한 경우

//컴파일 전 소스파일
String str4 = ""
            .concat("0")
            .concat("1")
            .concat("2");
//컴파일 이 후, 디컴파일 한 소스파일
String str4 = "".concat("0").concat("1").concat("2");

한줄로 선언하더라도 concat() 메서드를 사용한 경우는 StringBuilder로 변환되지 않습니다. 성능저하가 발생하게 됩니다. 따라서 이런 경우에는 StringBuilder 혹은 StringBuffer를 사용하여 성능최적화를 해야합니다.

결론

String 연산은 +를 사용하여 한줄로 선언하는 경우에만 성능저하가 발생하지 않는다. 여러줄에 걸쳐서 연산해야하는 경우는 명시적으로 StringBuilder를 사용해야 한다. 

반응형
댓글