Look at the following code:
Public class Main { publicstaticvoid main (string[] args) { = ""; for (int i=0;i<10000;i++) { + = "Hello";}} }
This string + = "Hello", the procedure is equivalent to the original string variable point to the object contents of the "Hello" as a string addition to the next one to save into another new string object, and then the string variable point to the newly generated object.
It is clear from this decompile bytecode file that starting from line 8th to line 35th is the execution of the entire loop, and each time the loop is new to a StringBuilder object, then the append operation is performed, and finally the string object is returned by the ToString method. In other words, this loop is finished. New has 10,000 objects, imagine, if these objects are not recycled, it will cause a lot of memory resources wasted. It can also be seen from the above that the operation of string+= "Hello" is in fact automatically optimized by the JVM:
New StringBuilder (string); Str.append ("Hello"); str.tostring ();
Let's look at the following code:
Public class Main { publicstaticvoid main (string[] args) { new StringBuilder (); for (int i=0;i<10000;i++) { stringbuilder.append ("Hello"); }}}
The anti-compile bytecode file gets:
It can be seen from here that the for loop of this code ends at 13 lines to 27 lines, and the new operation is done only once, i.e. only one object is generated, and the append operation is based on the original object. So after 10,000 cycles, this code takes up much less resources than the above.
Then some people will ask, since the StringBuilder class, why do you need StringBuffer class? See the source code at a glance, in fact, the StringBuilder and StringBuffer classes have the same member properties and member methods are basically the same, the difference is the StringBuffer class of member methods before a keyword: synchronized, do not say more, This keyword is secured during multithreaded access, meaning that StringBuffer is thread-safe.
The following is a 2 snippet of code from the StringBuffer and Stringbuilder,insert methods of the specific implementation:
Insert method for StringBuilder
Public StringBuilder Insert (intcharint offset, int len) { Super. Insert (index, str, offset, len); return This ; }
Insert method for StringBuffer:
Public synchronized StringBuffer Insert (intcharint offset, int len) { Super. Insert (index, str, offset, len); return This ; }
Performance testing
Public classMain {Private Static intTime = 50000; Public Static voidMain (string[] args) {teststring (); Teststringbuffer (); Teststringbuilder (); Test1string (); Test2string (); } Public Static voidteststring () {String s=""; LongBegin =System.currenttimemillis (); for(inti=0; i<time; i++) {s+ = "Java"; } Longover =System.currenttimemillis (); System.out.println ("Operation" +s.getclass (). GetName () + "type used for:" + (Over-begin) + "MS"); } Public Static voidTeststringbuffer () {StringBuffer sb=NewStringBuffer (); LongBegin =System.currenttimemillis (); for(inti=0; i<time; i++) {sb.append ("Java"); } Longover =System.currenttimemillis (); System.out.println ("Operation" +sb.getclass (). GetName () + "type used for:" + (Over-begin) + "MS"); } Public Static voidTeststringbuilder () {StringBuilder sb=NewStringBuilder (); LongBegin =System.currenttimemillis (); for(inti=0; i<time; i++) {sb.append ("Java"); } Longover =System.currenttimemillis (); System.out.println ("Operation" +sb.getclass (). GetName () + "type used for:" + (Over-begin) + "MS"); } Public Static voidtest1string () {LongBegin =System.currenttimemillis (); for(inti=0; i<time; i++) {String s= "I" + "Love" + "Java"; } Longover =System.currenttimemillis (); System.out.println ("String Direct Add Operation:" + (Over-begin) + "millisecond"); } Public Static voidtest2string () {String S1= "I"; String S2= "Love"; String S3= "Java"; LongBegin =System.currenttimemillis (); for(inti=0; i<time; i++) {String s= s1+s2+S3; } Longover =System.currenttimemillis (); System.out.println ("String Indirect add Operation:" + (Over-begin) + "millisecond"); } }
Results
The above mentioned string+= "Hello" operation is actually automatically optimized by the JVM, see the following code:
Public classMain {Private Static intTime = 50000; Public Static voidMain (string[] args) {teststring (); Testoptimalstring (); } Public Static voidteststring () {String s=""; LongBegin =System.currenttimemillis (); for(inti=0; i<time; i++) {s+ = "Java"; } Longover =System.currenttimemillis (); System.out.println ("Operation" +s.getclass (). GetName () + "type used for:" + (Over-begin) + "MS"); } Public Static voidtestoptimalstring () {String s=""; LongBegin =System.currenttimemillis (); for(inti=0; i<time; i++) {StringBuilder sb=NewStringBuilder (s); Sb.append ("Java"); S=sb.tostring (); } Longover =System.currenttimemillis (); System.out.println ("The time to simulate JVM optimization operations is:" + (Over-begin) + "milliseconds"); } }
Be verified.
The following is a general explanation of the results of the above implementation:
1) for the direct addition of strings, the efficiency is very high, because the compiler determines its value, that is, the shape of "I" + "Love" + "Java"; Strings are added, and are optimized for "Ilovejava" during compilation. This can be verified by using the JAVAP-C command to decompile the generated class file.
For the indirect addition (that is, contains the string reference), the shape is like s1+s2+s3; Efficiency is lower than the direct add, because the compiler does not optimize the reference variable.
2) execution efficiency of String, StringBuilder, StringBuffer:
StringBuilder > StringBuffer > String
Of course this is relative, not necessarily in all cases.
For example, string str = "Hello" + "world" is more efficient than StringBuilder st = new StringBuilder (). Append ("Hello"). Append ("World") is higher.
Therefore, these three classes are each with pros and cons and should be used according to different circumstances:
It is recommended to use string str= "Hello" in the case of a string addition or less modification;
It is recommended to use StringBuilder when the string addition operation is large, and stringbuffer if multi-threading is used.
On the face question of string and StringBuffer
1. What is the output of the following code?
String a = "Hello2"= "Hello" + 2= = b));
The output is: true. The reason is simple: "Hello" +2 has been optimized for "Hello2" during compilation, so the variable A and variable B point to the same object during run time.
2. What is the output of the following code?
String a = "Hello2"; = "Hello"; = B + 2; = = c));
The output is: false. Because of the existence of a symbolic reference, String C = B + 2, is not optimized during compilation, does not treat b+2 as a literal constant, so objects generated in this manner are actually stored on the heap. So a and C point to not the same object. What the javap-c get:
3. What is the output of the following code?
String a = "Hello2"; Final String b = "Hello"; = B + 2; = = c));
The output is: true. For a final modified variable, a copy is saved in the class file constant pool, that is, not accessed through a connection, and access to the final variable is directly substituted for the actual value during compilation. Then string c = B + 2, which is optimized during compilation: string c = "Hello" + 2;
4. The following code outputs the result:
Public class Main { publicstaticvoid main (string[] args) { = "Hello2"; final String b = Gethello (); = B + 2; = = c)) ; } Public Static String Gethello () { return "Hello"; }}
The output is false. Although the B is decorated with final, but because its assignment is returned through a method call, its value can only be determined during run time, so a and C point to not the same object.
5. What is the output of the following code?
public class Main { static void main (string[] args) {String A = "Hello" ; String b = new String ("Hello" = new String ("Hello" = B.intern (); System.out.println (a ==b); System.out.println (b ==c); System.out.println (b ==d); System.out.println (a ==d); }}
This involves the use of the String.intern method. In the string class, the Intern method is a local method, and before Java SE6, the Intern method looks for a string that has the same content in the run-time pool, returns a reference to the string if it exists, and, if it does not, the string into the pool. and returns a reference to the string. As a result, a and D point to the same object.
6.String str = new String ("ABC") The number of objects created
There is no reasonable answer to this question, and most of the online and some interview books are said to be 2 objects (one is "XYZ", and the other refers to the "XYZ" Reference object s), this is one-sided.
What is wrong with the problem? It does not define the meaning of "created".
What do you mean, "created"? When did you create it?
And does this Java code fragment actually "create two instances of string" when it runs?
If this is an interview question, then you can ask the interviewer to clarify the definition of "created" in person, and then answer accordingly. This time the interviewer will probably let the interviewee explain himself, that is good to do, and good sun to the interviewer to see.
If it is a written question, there is no chance to ask for clarification. However, the local level of this problem is mostly not good. Perhaps the question is from a variety of treasure to copy the title, then follow the book to the wrong answer written up can be mixed up
Let's change to another question:
string s = new string ("xyz"); How many string instances are involved at run time?
A reasonable solution is:
Two, one is the instance of the string literal "xyz" that resides (intern) in a globally shared string constant pool, and the other is an instance of the same content as "XYZ" created and initialized with the new string (string)
That is, the Java language is generally compiled into the Java Virtual Machine specification defined by the class file, but does not specify "must", leaving no JVM to implement the Java language of the room.
Considering the Java Virtual Machine specification, it is true that in this code the constant type of Constant_string_info string constant is also only "XYZ". Constant_string_info is a constant type used to represent the value of a constant expression of type string in the Java language (including string literals), which is only considered at this level, and this solution is no problem.
So this kind of solution can be considered reasonable.
It is worth noting that the "at runtime" of the problem includes both the class loading phase and the time the code fragment itself executes.
string s = new string ("xyz"); Several string types of variables that involve user claims?
One, which is string S.
String s = null; Several string types of variables that involve user claims?
String S1 = "a"; = S1.concat (""); NULL ; New String (S1);
This code involves 3 variables of type string,
1, S1, pointing to 1 of the following string instances
2, S2, pointing to the same as S1
3, S3, value NULL, not pointing to any instance
and 3 instances of string,
1. String instance of the "a" literal corresponding to the resident string constant
2. String instance of "" literal corresponding to the resident string constant
(String.Concat () is an interesting way to return this when it is found that an incoming parameter is an empty string, so there is no additional string instance created here.
3. New string instance created by new string, without any variables pointing to it.
.... Specific discussion Consult http://rednaxelafx.iteye.com/blog/774673/
7. What is the difference between the following code 1) and 2?
Public class Main { publicstaticvoid main (string[] args) { = "I"; // str1 + = "Love" + "Java"; 1) str1 = str1+ "Love" + "Java"; // 2) }}
1) is more efficient than 2, and 1) in the "Love" + "Java" will be optimized during compilation to "Lovejava", and 2) will not be optimized.
Java Foundation-string, StringBuffer, StringBuilder