Java 문자열 맞춤법 상세 정보
변경할 수 없는 String 객체
Java에서 String 객체는 변경할 수 없습니다(Immutable).코드에서 여러 개의 String 객체에 대한 별칭을 만들 수 있습니다.하지만 이 별명들은 모두 인용이 같다.
예를 들어 s1과 s2는 모두'droidyue'입니다.com 객체의 별칭입니다. 별칭은 실제 객체에 대한 참조로 저장됩니다.그래서 s1 = s2
String s1 = "droidyue.com";
String s2 = s1;
System.out.println("s1 and s2 has the same reference =" + (s1 == s2));
Java에만 있는 재부팅 연산자Java에서 재부팅되는 유일한 연산자는 문자열의 결합과 관련된 것입니다. +, +=.이외에도 Java 디자이너는 다른 연산자를 다시 로드할 수 없습니다.
결합 분석
정말 성능 대가가 있나
위의 두 가지를 이해하면 이러한 사고가 있을 수 있다. 만약에 Sting 대상이 변하지 않는다면 여러 개의 (3개 이상) 문자열 결합은 반드시 불필요한 중간 String 대상이 생길 것이다.
String userName = "Andy";
String age = "24";
String job = "Developer";
String info = userName + age + job;
위의 info를 얻으려면userName과age 연결이 임시 String 대상 t1을 생성합니다. 내용은 Andy24이고 t1과job 연결이 최종적으로 우리가 필요로 하는 info 대상을 생성합니다. 그 중에서 중간 t1이 생성되었고 t1이 생성된 후에 자발적으로 회수하지 않으면 일정한 공간을 차지할 것입니다.만약 많은 문자열 (수백 개를 가정하면 대상에 대한 toString의 호출에 많이 나타난다) 의 결합이라면 대가가 더욱 커지고 성능이 한꺼번에 많이 떨어질 것이다.컴파일러의 최적화 처리
정말 위의 성능 대가가 있을까요? 문자열 연결이 이렇게 자주 사용되는데 특별한 처리 최적화가 없습니까? 답은 있습니다. 이 최적화는 컴파일러에서 컴파일됩니다.java가bytecode에 도착했을 때.
Java 프로그램을 실행하려면 컴파일할 때와 실행할 때 두 시기를 거쳐야 한다.컴파일할 때, 자바 컴파일러는 자바 파일을 바이트 코드로 변환합니다.런타임 시 JVM(JVM)이 컴파일을 실행할 때 생성된 바이트 코드입니다.이러한 두 시기를 통해 자바는 이른바 컴파일링을 하고 곳곳에서 운행했다.
우리는 컴파일러가 어떤 최적화를 했는지 실험해 보자. 우리는 성능 대가가 발생할 수 있는 코드를 제조한다.
public class Concatenation {
public static void main(String[] args) {
String userName = "Andy";
String age = "24";
String job = "Developer";
String info = userName + age + job;
System.out.println(info);
}
}
네, Concatenation.java를 컴파일해 보세요.Concatenation을 얻다.classjavac Concatenation.java
그리고 우리는 javap를 사용하여 컴파일된 Concatenation을 역컴파일합니다.class 파일.javap -c Concatenation.만약javap 명령을 찾지 못하면, javap가 있는 디렉터리를 환경 변수에 추가하거나 javap의 전체 경로를 사용하는 것을 고려하십시오.
17:22:04-androidyue~/workspace_adt/strings/src$ javap -c Concatenation
Compiled from "Concatenation.java"
public class Concatenation {
public Concatenation();
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 Andy
2: astore_1
3: ldc #3 // String 24
5: astore_2
6: ldc #4 // String Developer
8: astore_3
9: new #5 // class java/lang/StringBuilder
12: dup
13: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V
16: aload_1
17: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
20: aload_2
21: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
24: aload_3
25: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
31: astore 4
33: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream;
36: aload 4
38: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
41: return
}
그 중에서ldc,astore 등은 자바 바이트 코드의 지령으로 어셈블리 지령과 유사하다.다음 설명에서는 Java 관련 컨텐트를 사용하여 설명합니다.우리는 위에 많은 StringBuilder가 있는 것을 볼 수 있지만, 우리는 자바 코드에서 표시적으로 호출하지 않는다. 이것이 바로 자바 컴파일러가 최적화한 것이다. 자바 컴파일러가 문자열 연결을 만났을 때 StringBuilder 대상, 뒤에 있는 연결을 만들 것이다. 실제로는 StringBuilder 대상을 호출하는 append 방법이다.이렇게 하면 우리 위에서 걱정하는 문제가 없을 것이다.컴파일러만으로 최적화?
컴파일러가 우리를 도와 최적화를 한 이상 컴파일러의 최적화만으로 충분하지 않겠는가, 물론 그렇지 않다.
다음은 최적화되지 않은 성능이 낮은 코드를 보겠습니다.
public void implicitUseStringBuilder(String[] values) {
String result = "";
for (int i = 0 ; i < values.length; i ++) {
result += values[i];
}
System.out.println(result);
}
javac 컴파일, javap로 보기
public void implicitUseStringBuilder(java.lang.String[]);
Code:
0: ldc #11 // String
2: astore_2
3: iconst_0
4: istore_3
5: iload_3
6: aload_1
7: arraylength
8: if_icmpge 38
11: new #5 // class java/lang/StringBuilder
14: dup
15: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V
18: aload_2
19: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: aload_1
23: iload_3
24: aaload
25: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
31: astore_2
32: iinc 3, 1
35: goto 5
38: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream;
41: aload_2
42: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
45: return
그중 8: if_icmpge38과 35:goto5는 하나의 순환을 구성한다.8: if_icmpge 38은 JVM 작업 스택의 정수 대비가 (i 조금만 최적화하면 순간적으로 압박을 증가시킵니다.
public void explicitUseStringBuider(String[] values) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < values.length; i ++) {
result.append(values[i]);
}
}
컴파일된 정보
public void explicitUseStringBuider(java.lang.String[]);
Code:
0: new #5 // class java/lang/StringBuilder
3: dup
4: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V
7: astore_2
8: iconst_0
9: istore_3
10: iload_3
11: aload_1
12: arraylength
13: if_icmpge 30
16: aload_2
17: aload_1
18: iload_3
19: aaload
20: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
23: pop
24: iinc 3, 1
27: goto 10
30: return
위에서 보듯이 13:if_icmpge 30과 27: goto 10은 loop 순환을 구성하고 0: new #5는 순환 밖에 있기 때문에 StringBuilder를 여러 번 만들지 않습니다.전반적으로 말하자면, 우리는 순환체에서 스텔스나 현식으로 StringBuilder를 만드는 것을 최대한 피해야 한다.그래서 코드를 어떻게 컴파일하고 내부에서 어떻게 실행하는지 아는 사람들은 코드의 등급이 비교적 높다.
상기 문장에 만약 잘못이 있으면 비판하고 바로잡아 주십시오.
이상은 자바 문자열의 연결에 대한 자료를 정리하고 관련 자료를 계속 보충합니다. 본 사이트에 대한 지지에 감사드립니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.