티스토리 뷰
Java 문자열 연결 연산 동작 메커니즘
- Java String을 다루다 보면 문자열 조합을 위해서 + 연산자를 사용하는 경우가 많습니다.
- 아래 예제를 실행하게 되면 내부에서는 어떤 동작이 이루어질까요?
public class Application {
public static void main(String[] args) {
String s1 = "afas";
String s2 = "asfasfaasf";
String s3 = s1 + s2;
System.out.println(s3);
}
}
검색을 해보자.
- StackOverFlow를 찾아보니 이런 내용이 있습니다.
+ 연산자는 Java 컴파일러에서 구현이 되며 String + String 연산은 컴파일 타임에 상수 혹은 StringBuilder 코드로 변환된다.
Byte Code를 까보자.
- 위 코드를 컴파일 하고 클래스 파일을 javap 를 이용하여 바이트 코드를 확인해볼 수 있습니다.
- 참고로 JDK 1.8 환경입니다.
> javac Application.java
> javap -c Application.class
-
우선 main 메서드의 0:, 3: 라인에서
s1
을 "afas",s2
를 "asfasfaasf"로 할당하는 것을 확인해볼 수 있습니다.- ldc는 상수를 실행 스택에 푸쉬 하는 OP Code 이며 문자열은 String Pool에 저장된 뒤에 가져와지는 방식
- String Pool, String 객체 생성 방법에 대한 부분은 아래 포스팅을 참고하시면 좋습니다.
-
6: 라인에서
StringBuilder
객체가 생성되고 14:, 18: 라인에서StringBuilder
의append()
메소드가 호출되고 (흠 .. 어떤 객체가 전달되는지는 알수 없군요) 21: 라인에서StringBuilder
의toString()
메소드가 호출됩니다.invokevirtual
은 인스턴스 메소드를 호출하는 OP Code 입니다.
public class com.jinseong.soft.string.Application {
public com.jinseong.soft.string.Application();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String afas
2: astore_1
3: ldc #3 // String asfasfaasf
5: astore_2
6: new #4 // class java/lang/StringBuilder
9: dup
10: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
13: aload_1
14: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: aload_2
18: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
24: astore_3
25: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
28: aload_3
29: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
32: return
-
문맥상 컴파일 타임에 String s3 = s1 + s2; 코드는 아래처럼 변환되는 것을 유추해볼 수 있겠군요.
StringBuilder builder = new StringBuilder();
builder.append(s1);
builder.append(s2);
String s3 = builder.toString();
그럼 왜 String 문자열 연결이 느린가?
(이펙티브 자바) 규칙63. 문자열 연결은 느리니 주의하라
-
위에서 본 바로는 문자열 연결 연산을 하게 되면 StringBuilder 로 변환되어 연결 연산을 수행한다고 하지 않았나 ?
까보자.
-
눈으로 확인해봐야 겠습니다.
void testString() {
long startTime = System.currentTimeMillis();
String result = "";
for(int i=0; i<100000; i++){
result += "abcd";
}
long endTime = System.currentTimeMillis();
System.out.println("걸린 시간 : " + (float)(endTime-startTime)/1000 + "초");
}
void testStringBuilder() {
long startTime = System.currentTimeMillis();
StringBuilder builder = new StringBuilder(4 * 100000);
for(int i=0; i<100000; i++){
builder.append("abcd");
}
String result = builder.toString();
long endTime = System.currentTimeMillis();
System.out.println("걸린 시간 : " + (float)(endTime-startTime)/1000 + "초");
}
//걸린 시간 : 18.801초
//걸린 시간 : 0.002초
- 아래는 for문 부근에 대한 각각의 바이트 코드입니다. (정답은 간단했습니다..)
StringBuilder
를 내부적으로 사용하긴 하지만 매번 새로 생성되어append()
연산을 한 후 다시 String으로 변환되는 방식 입니다.
//testString()
17: new #7 // class java/lang/StringBuilder
20: dup
21: invokespecial #8 // Method java/lang/StringBuilder."<init>":()V
24: aload_3
25: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: ldc #10 // String abcd
30: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
33: invokevirtual #11 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
36: astore_3
37: iinc 4, 1
40: goto 10
//testStringBuilder()
21: if_icmpge 37
24: aload_3
25: ldc #10 // String abcd
27: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
30: pop
31: iinc 4, 1
34: goto 17
관련글
반응형
'프로그래밍 > JAVA' 카테고리의 다른 글
[kotlin/java/spring] 토스 페이먼츠 자동결제 (billing) 연동 방법 - 1. Billing Key 발급 (5) | 2022.10.19 |
---|---|
[Java] String 객체는 어떻게 저장될까? (0) | 2021.01.22 |
[Java] System 환경 변수 가져오는 방법 (0) | 2020.11.09 |
[Java] Application Uncaught Exception 기본 핸들러 설정 방법 (0) | 2020.11.07 |
[Java] String <-> ZonedDate Time 변환 방법 (0) | 2020.11.06 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- JavaFX
- 일본 여행
- JavaFX 종료
- springboot
- Java UI
- 방통대 과제물
- 자바
- windows
- intelij
- effectivejava
- 이펙티브 자바
- effective java
- 일본 자전거 여행
- 일본여행
- 이펙티브자바
- 자전거
- 텐트
- java
- 스프링부트
- git
- JavaFX Window Close
- JavaFX Table View
- 인텔리제이
- 이펙티브
- 배낭 여행
- TableView
- 배낭여행
- 일본 배낭여행
- 자전거 여행
- JavaFX 테이블뷰
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
글 보관함