문자열 생성
String 문자열을 연결할 때 아래와 같이 객체로써 선언해서 사용할 경우 불필요한 객체가 만들어진다는걸 우리는 알고있다.
String temp = new String("wedul");
그래서 String을 아래와 같이 선언해서 String constants Pool에 저장해서 불변객체를 생성해서 동일한 문자열에 대해서 새로 생성하지 않고 가져다 사용할 수 있도록 할수있다. (effective java. 불필요한 객체를 만들지 마라.)
String temp = "wedul"
문자열 연결
문자열 생성 시 우리는 + 로 문자열을 연결할 경우 새로운 문자열 객체가 계속 생성되기 때문에 이를 해결하기 위해서 StringBuilder를 통해서 모든 append가 끝나고 build를 통해 문자열 객체를 한번만 생성하라고 배웠었다.
하지만 이 부분은 jdk 1.5 버전 부터는 컴파일 시에 자동으로 +를 사용해도 StringBuilder를 사용하는 형태로 바꿔주기 때문에 굳이 문자열을 concat할 때 StringBuilder를 사용하지 않아도 되었다.
ex)
java.lang.String concat(java.lang.String, int);
Code:
0: new #2 // class StringBuilder
3: dup
4: invokespecial #3 // Method StringBuilder."<init>":()V
7: aload_0
8: invokevirtual #4 // Method StringBuilder.append:(LString;)LStringBuilder;
11: iload_1
12: invokevirtual #5 // Method StringBuilder.append:(I)LStringBuilder;
15: invokevirtual #6 // Method StringBuilder.toString:()LString;
하지만 +의 형태를 StringBuilder의 형태로 변경을 해주다 보니 loop의 상황에서는 아래와 같이 계속해서 StringBuilder객체가 생성되는 문제가 발생한다.
// 작성한 코드
String temp = "";
for (int i = 0; i < 10; i++) {
temp += i;
}
// 디컴파일 코드
String temp = "";
for (int i = 0; i < 10; i++) {
temp = (new StringBuilder()).append(i).toString();
}
이런 문제를 해결하기 위해 jdk 1.9버전 부터는 StringBuilder가 아닌 makeConcatWithConstants을 사용하여 문자열을 붙이도록 변경되었다.
https://www.baeldung.com/java-string-concatenation-invoke-dynamic
https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/StringConcatFactory.html
Warning: File ./Test.class does not contain class Test
Classfile /Users/wedul/Documents/project/algorizmtest/src/tt/Test.class
Last modified 2022. 10. 31.; size 1087 bytes
SHA-256 checksum 9a1511286f28216ac376bebae126abd8f0d64b48ddc22d00d54c91c07dd0e25c
Compiled from "Test.java"
public class tt.Test
minor version: 0
major version: 61
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #10 // tt/Test
super_class: #2 // java/lang/Object
interfaces: 0, fields: 0, methods: 3, attributes: 3
Constant pool:
#1 = Methodref #2.#3 // java/lang/Object."<init>":()V
#2 = Class #4 // java/lang/Object
#3 = NameAndType #5:#6 // "<init>":()V
#4 = Utf8 java/lang/Object
#5 = Utf8 <init>
#6 = Utf8 ()V
#7 = String #8 // test
#8 = Utf8 test
#9 = Methodref #10.#11 // tt/Test.reversString:(Ljava/lang/String;)Ljava/lang/String;
#10 = Class #12 // tt/Test
#11 = NameAndType #13:#14 // reversString:(Ljava/lang/String;)Ljava/lang/String;
#12 = Utf8 tt/Test
#13 = Utf8 reversString
#14 = Utf8 (Ljava/lang/String;)Ljava/lang/String;
#15 = Fieldref #16.#17 // java/lang/System.out:Ljava/io/PrintStream;
#16 = Class #18 // java/lang/System
#17 = NameAndType #19:#20 // out:Ljava/io/PrintStream;
#18 = Utf8 java/lang/System
#19 = Utf8 out
#20 = Utf8 Ljava/io/PrintStream;
#21 = Methodref #22.#23 // java/io/PrintStream.println:(Ljava/lang/String;)V
#22 = Class #24 // java/io/PrintStream
#23 = NameAndType #25:#26 // println:(Ljava/lang/String;)V
#24 = Utf8 java/io/PrintStream
#25 = Utf8 println
#26 = Utf8 (Ljava/lang/String;)V
#27 = Class #28 // java/lang/String
#28 = Utf8 java/lang/String
#29 = String #30 // wedul
#30 = Utf8 wedul
#31 = Methodref #27.#32 // java/lang/String."<init>":(Ljava/lang/String;)V
#32 = NameAndType #5:#26 // "<init>":(Ljava/lang/String;)V
#33 = String #34 //
#34 = Utf8
#35 = Methodref #27.#36 // java/lang/String.toCharArray:()[C
#36 = NameAndType #37:#38 // toCharArray:()[C
#37 = Utf8 toCharArray
#38 = Utf8 ()[C
#39 = InvokeDynamic #0:#40 // #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
#40 = NameAndType #41:#14 // makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
#41 = Utf8 makeConcatWithConstants
#42 = Utf8 Code
#43 = Utf8 LineNumberTable
#44 = Utf8 main
#45 = Utf8 ([Ljava/lang/String;)V
#46 = Utf8 SourceFile
#47 = Utf8 Test.java
#48 = Utf8 BootstrapMethods
#49 = MethodHandle 6:#50 // REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
#50 = Methodref #51.#52 // java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
#51 = Class #53 // java/lang/invoke/StringConcatFactory
#52 = NameAndType #41:#54 // makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
#53 = Utf8 java/lang/invoke/StringConcatFactory
#54 = Utf8 (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
#55 = String #56 // \u0001111
#56 = Utf8 \u0001111
#57 = Utf8 InnerClasses
#58 = Class #59 // java/lang/invoke/MethodHandles$Lookup
#59 = Utf8 java/lang/invoke/MethodHandles$Lookup
#60 = Class #61 // java/lang/invoke/MethodHandles
#61 = Utf8 java/lang/invoke/MethodHandles
#62 = Utf8 Lookup
{
public tt.Test();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 3: 0
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=3, args_size=1
0: ldc #7 // String test
2: invokestatic #9 // Method reversString:(Ljava/lang/String;)Ljava/lang/String;
5: astore_1
6: getstatic #15 // Field java/lang/System.out:Ljava/io/PrintStream;
9: aload_1
10: invokevirtual #21 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
13: new #27 // class java/lang/String
16: dup
17: ldc #29 // String wedul
19: invokespecial #31 // Method java/lang/String."<init>":(Ljava/lang/String;)V
22: astore_2
23: return
LineNumberTable:
line 6: 0
line 7: 6
line 8: 13
line 9: 23
public static java.lang.String reversString(java.lang.String);
descriptor: (Ljava/lang/String;)Ljava/lang/String;
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=3, args_size=1
0: ldc #33 // String
2: astore_1
3: aload_0
4: invokevirtual #35 // Method java/lang/String.toCharArray:()[C
7: astore_2
8: aload_1
9: invokedynamic #39, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
14: astore_1
15: aload_1
16: invokedynamic #39, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
21: astore_1
22: aload_1
23: invokedynamic #39, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
28: astore_1
29: aload_1
30: invokedynamic #39, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
35: astore_1
36: aload_1
37: areturn
LineNumberTable:
line 12: 0
line 13: 3
line 15: 8
line 16: 15
line 17: 22
line 18: 29
line 23: 36
}
SourceFile: "Test.java"
BootstrapMethods:
0: #49 REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
Method arguments:
#55 \u0001111
InnerClasses:
public static final #62= #58 of #60; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
'JAVA > 고급 자바' 카테고리의 다른 글
모던 자바 인 액션 내용 정리 (0) | 2020.04.12 |
---|---|
Java 메모리 구조 및 GC 알고리즘 정리 (0) | 2019.09.23 |
[공유] 자바 유료화 관련 글 공유 (0) | 2018.10.04 |
Iterator 그리고 Iterable에 대해 정리 (0) | 2018.10.04 |
static method와 Override hiding 대한 정리 (0) | 2018.10.04 |