Java의 문자열에 대한 질문을 고려해 봅시다 : "ABC" + '/'와 "ABC" + "/"의 차이점. 이 예를 통해 JDK 도구에서 JAVAP 사용을 연습 할 수 있습니다. 원래 질문은 다음과 같습니다.
슬래시/문자 또는 문자열 치료의 차이점은 무엇입니까?
하나는 기본 데이터 유형 Char로 사용되고 다른 하나는 객체 문자열입니다. 구체적인 차이는 무엇입니까?
그것을 캐릭터로 취급하는 것이 더 효율적입니까?
문자열 str = "abc" + '/';
그리고
문자열 str = "abc" + "/";
1. 컴파일러 최적화
우선, 위의 두 문장은 동일한 효과를 가지고 있음을 알아야합니다. 컴파일러는 위의 두 문장을 다음과 같이 최적화하기 때문입니다.
문자열 str = "abc/";
우리는 Javap을 통해 이것을 증명할 수 있습니다. Javap의 경우 "모든 Java 개발자가 알아야 할 5 JDK 도구"를 참조하십시오. 먼저 Class : StringOne을 생성하고 주요 방법에서 다음 코드를 작성합니다.
StringOne.javastring str1 = "abc" + '/'; String str2 = "abc" + "/" ;system.out.println(str1 == str2);
컴파일 및 실행, 출력 결과는 사실입니다. 다음으로 Javap이 시작되면 명령 줄에 다음 명령을 입력하십시오.
javap -v -l stringone.class> stringone.s
그런 다음 생성 된 StringOne.s 파일을 확인하십시오. 당신은 그 안에 여러 줄이 있다는 것을 알게 될 것입니다
StringOne.s #2 = String #20 // abc /..
설명 : str1 및 str2는 둘 다 문자열 "abc/"를 참조하십시오.
2. Javap을 사용하여 차이를 분석하십시오
이제 질문을 바꾸겠습니다. 다음 코드의 StringAddstring과 StringAddchar 메소드의 차이점은 무엇입니까?
StringTwoPublic static String StringAddstring (String Str1, String Str2) {return str1 + str2;} public static String StringAddchar (String Str, char ch) {return str + ch;}이번에는 Javap이 해석에 사용되며 생성 된 파일의 일부 내용은 다음과 같습니다.
StringTwo.spublic java.lang.string StringAddstring (java.lang.string, java.lang.string); 설명 자 : (ljava/lang/string; ljava/lang/string;) ljava/lang/string; 플래그 : ACC_PUBLIC CODE : Stack = 2, Locals = 3, Args_Size = 3 0 : New #2 // 클래스 Java/Lang/StringBuilder 3 : Dup 4 : invokescial #3 // 메소드 Java/Lang/StringBuilder. "<init>":() v 7 : aload_1 8 : The JAVA/LANG/LANGBIRTEUDE. 추가 : (ljava/lang/string;) ljava/lang/stringbuilder; 11 : aload_2 12 : invokevirtual #4 // 메소드 java/lang/stringbuilder. 추가 : (ljava/lang/string;) ljava/lang/stringbuilder; 15 : InvokeVirtual #5 // 메소드 Java/Lang/StringBuilder. 토스트 링 :() ljava/lang/string; 18 : areturnpublic java.lang.string StringAddchar (java.lang.string, char); 설명 자 : (ljava/lang/string; c) ljava/lang/string; 플래그 : ACC_PUBLIC 코드 : 스택 = 2, 로컬카 = 3, args_size = 3 0 : 새로운 #2 // 클래스 java/lang/stringbuilder 3 : dup 4 : invokespecial #3 // 메소드 java/lang/stringbuilder. "<init>":() v 7 : aload_1 8 : // Java/Lang/StringBuilder.Append : (ljava/lang/string;) ljava/lang/stringbuilder; 11 : iload_2 12 : invokevirtual #6 // 메소드 java/lang/stringbuilder.append : (c) ljava/lang/stringbuilder; 15 : InvokeVirtual #5 // 메소드 Java/Lang/StringBuilder.tostring :() ljava/lang/string; 18 : Areturn
이제이 두 가지 방법을 실행하는 과정을 명확하게 볼 수 있습니다.
StringAddstring
StringAddchar의 절차는 StringAddString과 동일합니다. 부록 메소드가 두 번째로 불리는 경우 StringAddstring의 매개 변수는 String 유형이며 StringAddchar의 매개 변수는 char 유형입니다.
3. stringbuilder 클래스의 (문자열) 메소드 (문자열) 메소드 (문자열) 방법
여기서는 소스 코드를 직접 확인하면됩니다 (Mine은 JDK1.8.0_60과 함께 제공되는 소스 코드). 문서는 StringBuilder가 소스 코드에서 Object에서 상속되는 것을 보여 주지만, Abstract Class AbstractStringBuilder에서 상속됩니다. Append 방법은 AbstractStringBuilder에 의해 구현됩니다.
AbstractStringBuilder.java
Public AbstractStringBuilder Append (char c) {ensurecapacity internal (count + 1); // 배열이 카운트+1 자 값을 수용 할 수 있는지 확인하십시오 [count ++] = c; return;} public acpractStringBuilder append (string str) {if (str == null) return accendnull (); int len = str.length (); ensurecapacity internal (count + len); str.getchars (0, len, 값, 카운트); // 문자열의 문자 배열을 문자열 배열을이 객체의 문자 배열로 복사합니다 count += len; 이것을 반환하십시오;}나머지는 더 이상 게시되지 않습니다. String.getChars (int, int, char [], int)는 궁극적으로 공개 정적 네이티브 void arraycopy (Object, int, Object, int, int)에 따라 다릅니다. 다시 말해, C 언어로 작성 될 수 있으며 Java로 작성된 프로그램보다 큰 배열을 복사 할 때 효율성이 더 나을 수 있습니다. 이제 내가 이해하는 것을 말씀 드리겠습니다.
직접 메모리 측면에서 문자열에는 숯 배열이 포함되어 있으므로 배열의 길이 필드가 있어야합니다. 동시에 문자열 클래스에는 int 해시 속성이 있으며 객체 자체는 다른 정보를 저장하기 위해 추가 메모리를 점유하므로 문자열은 더 많은 메모리를 차지하게됩니다. 그러나 문자열이 매우 길면 이러한 메모리 오버 헤드는 거의 무시할 수 있습니다. 문자열이 (매우) 짧은 경우 이러한 메모리 오버 헤드를 공유 할 공유 참조가 많으므로 과도한 메모리 오버 헤드는 여전히 무시할 수 있습니다.
통화 스택에서 문자열은 여기에서 char보다 하나 또는 두 개의 함수 호출 만 있으므로 기능 호출 오버 헤드 (시간 및 공간 포함)가 고려되지 않으면 비슷해야합니다. 함수 호출 오버 헤드가 고려되면 "ABC" + '/'가 더 나을 것입니다. 그러나 여러 문자를 연결 해야하는 경우 (이 상황이 더 일반적이어야한다고 생각합니까?), Char를 사용하려면 많은 루프가 연결을 완료하기 위해 필요한 기능의 수는 문자열을 사용하는 것보다 더 호출됩니다. 동시에 복사는 배열을 직접 복사하는 문자열보다 빠르지 않습니다. 따라서 현재는 더 큰 처리량으로 "ABC" + "/"가됩니다.
이제이 질문이 묻는 것처럼 느낍니다. 파일을 읽고 읽을 때 시스템 호출을 사용하는 것이 더 효율적입니까, 아니면 표준 기능 라이브러리에서 IO 라이브러리를 사용하는 것이 더 효율적입니까? IO 라이브러리의 버퍼링 메커니즘으로 인해 표준 IO 라이브러리가 결국 시스템 호출을 통화해야하며 일부 임시 변수와 더 깊은 통화 스택이 생성 될 것이라고 생각합니다. IO 라이브러리의 버퍼링 메커니즘으로 인해 IO 라이브러리의 처리량이 커지고 시스템 호출의 실시간 성능이 향상됩니다. 마찬가지로, 문자열 클래스에는 더 많은 필드와 더 깊은 기능 스택이 있지만 캐시와 직접 복사로 인해 처리량이 더 좋습니다.
새로운 질문
위의 Javap 디 컴파일 코드에서 판단하면 두 줄이 함께 추가되면 StringBuilder의 문자열이 추가됩니다. 따라서 이론적으로 다음 중 어느 것이 더 효율적입니까?
문자열 str1 = "ABC" + "123"; // 1stringBuilder StringBuilder = new StringBuilder (); // 2stringBuilder.append ( "abc"); StringBuilder.append ( "123"); String str2 = StringBuilder.toString ();
이 질문이 모두가 생각할 수 있도록 맡기십시오!
위는이 기사의 모든 내용으로, Java의 String+String 및 String+Char를 더 잘 구별하는 데 도움이됩니다. 모든 사람의 학습에 도움이되기를 바랍니다.