Let's consider a question about a string in Java: The difference between "abc" + "/" and "abc" + "/". With this example, we can practice the use of JAVAP in the JDK tool by the way, as the original question goes:
What's the difference between a slash/a character or a string?
One is as basic data type char and one is object string. What difference does it have?
Is it more efficient as a character?
String str = "abc" + '/';
and
String str = "ABC" + "/";
1. Compiler optimization
First of all you should know that the above two sentences effect is the same, because the compiler will be the above two sentences are optimized into the following look:
We can prove this by JAVAP. For JAVAP, you can refer to the 5 JDK tools that every Java developer should know. Let's start by creating a class: Stringone, which fills in the following code in the Main method:
Stringone.java
String str1 = "abc" + '/';
String str2 = "abc" + "/";
System.out.println (str1 = = str2);
Compile and run and the output is true. Next, our JAVAP, enter the following command at the command line:
Javap-v-L stringone.class > STRINGONE.S
Then look at the generated stringone.s file. You'll find that there are a few lines.
STRINGONE.S
#2 = String #20 //abc/
...
#20 = Utf8 abc/...
0:LDC #2 //String abc/
2:astore_1
3:ldc #2 //String abc/
5:astore_2
Description str1 and STR2 both refer to the string "abc\".
2, the use of JAVAP analysis of differences
Now let's change the question, what is the difference between the stringaddstring and Stringaddchar methods in the following code?
Stringtwo public
static string stringaddstring (String str1, String str2) {return
str1 + str2;
}
public static string Stringaddchar (String str, char ch) {return
str + ch;
}
This time you use JAVAP to decompile, and some of the generated files are shown below
Stringtwo.s public java.lang.String stringaddstring (java.lang.String, java.lang.String); Descriptor: (ljava/lang/string;
ljava/lang/string;) ljava/lang/string;
Flags:acc_public code:stack=2, locals=3, args_size=3 0:new #2//Class Java/lang/stringbuilder 3:dup 4:invokespecial #3//Method Java/lang/stringbuilder. " < init> ":() V 7:aload_1 8:invokevirtual #4//Method Java/lang/stringbuilder.
Append: (ljava/lang/string;) Ljava/lang/stringbuilder; 11:aload_2 12:invokevirtual #4//Method Java/lang/stringbuilder.
Append: (ljava/lang/string;) Ljava/lang/stringbuilder; 15:invokevirtual #5//Method Java/lang/stringbuilder.
ToString: () ljava/lang/string;
18:areturn public java.lang.String Stringaddchar (java.lang.String, char); Descriptor: (ljava/lang/string;
C) ljava/lang/string;
Flags:acc_public code:stack=2, locals=3, args_size=3 0:new #2//Class Java/lang/stringbuilder 3: DUP 4:invokespecial #3//Method Java/lang/stringbuilder. " <init> ":() V 7:aload_1 8:invokevirtual #4//Method Java/lang/stringbuilder.append: (Ljava/lang/stri
ng;) Ljava/lang/stringbuilder;
11:iload_2 12:invokevirtual #6//Method Java/lang/stringbuilder.append: (C) Ljava/lang/stringbuilder;
15:invokevirtual #5//Method java/lang/stringbuilder.tostring: () ljava/lang/string;
18:areturn
Now, we can see clearly the process that the two methods are executing:
Stringaddstring
- Create a StringBuilder object
- Using the Append method, sequentially adds two parameters to the StringBuilder you just created.
- Call the ToString method.
- Returns the return value of the ToString method.
The Stringaddchar process is the same as stringaddstring, except that when the second call to the Append method the parameter stringaddstring is a string type, and the Stringaddchar parameter is a char type.
3. The Append (char) method of the StringBuilder class and the Append (String) method
Here, we directly look at the source code is good (I am jdk1.8.0_60 with the source code). Note that although the document shows StringBuilder inherited from object, it is inherited from the abstract class Abstractstringbuilder from the source. And the Append method is implemented by Abstractstringbuilder.
Abstractstringbuilder.java
Public Abstractstringbuilder Append (char c) {
ensurecapacityinternal (count + 1); Ensure that the array can hold count+1 characters
value[count++] = c;
return this;
}
Public Abstractstringbuilder append (String str) {
if (str = null) return
appendnull ();
int len = Str.length ();
Ensurecapacityinternal (count + len);
Str.getchars (0, Len, value, count); The character array in the copy string to the character array of this object,
count = Len;
return this;
}
The rest is no longer posted. String.getchars (int, int, char[], int) ultimately depend on the public static native void Arraycopy (object, int, object, int, int). In other words, it may be written in C, and the efficiency of copying large arrays should be better than those written in Java. So, now, let me say what I understand:
In the case of direct memory, because a string contains a char array, and the array should be of a length field, and the string class has an int hash property, plus the object itself consumes additional memory to store additional information, the string consumes a bit more memory. But if the string is very long, then the memory overhead can be almost negligible; And if the string comparison (very) is short in the case of "/", then there is likely to be a lot of shared references to share the memory overhead, so the extra memory overhead can be ignored.
From the call stack, because the string is only one or two-layer function calls than char, it should be almost the same if the function call overhead (including time and space) is not considered, and it should be "abc" + '/' better to consider the function call overhead; But when you need to connect a few words characters (this should be more common?), because using char requires several loops to complete the connection, the number of functions invoked will be more than string. The copy is also no faster than a string that copies an array directly. So this time it becomes the "ABC" + "/" throughput greater.
Now it feels like the question is: Is it efficient to use system calls when reading or writing files, or is it efficient to use an IO library in a standard function library? Personal feeling, although the standard IO library finally has to call the system call, and this will produce some temporary variables, as well as a deeper call stack, but due to the IO library buffer mechanism, so the IO library throughput will be greater, and the real-time system calls better. Similarly, although the string class will have several more fields and a deeper stack of functions, throughput should be better due to caching and more direct copies.
New issues
From the JAVAP code above, the addition of two strings becomes the append string to the StringBuilder. So in theory, which of the following code is efficient?
String str1 = "abc" + "123"; 1
StringBuilder StringBuilder = new StringBuilder ();//2
stringbuilder.append ("abc");
Stringbuilder.append ("123");
String str2 = stringbuilder.tostring ();
Let us think about this question!
The above is the entire content of this article, to help you better distinguish Java string+string and String+char, I hope to help you learn.