Abstract: This paper expounds and analyzes the principle of implementation: In the Java language, a variable of type String as a parameter of a method is a "non object" attribute.
First, the beginning of the example
The most important thing to write code is practice, without repeated experimentation, the rhetoric can only be said to be a figment of the imagination. So, in this article, let's start with a simple example to throw out the core topic:
public class Stringasparamofmethoddemo {public
static void Main (string[] args) {
Stringasparamofmethoddemo Stringasparamofmethoddemo = new Stringasparamofmethoddemo ();
Stringasparamofmethoddemo.testa ();
}
private void Testa () {
String originalstr = "original";
System.out.println ("Test A Begin:");
SYSTEM.OUT.PRINTLN ("The outer String:" + originalstr);
Simplechangestring (ORIGINALSTR);
SYSTEM.OUT.PRINTLN ("The outer String after inner change:" + originalstr);
System.out.println ("Test A end.");
System.out.println ();
}
public void Simplechangestring (String original) {
original = original + ' is changed! ';
System.out.println ("The changed inner String:" + original);
}
The logic of this code is this: first assign a string type of local variable, and then send the variable as a parameter into a method, in this method change the value of the variable. After the compilation is run, the output is found to be like this:
Test A Begin: The
outer string:original the
changed inner string:original is changed!
The outer String after inner change:original
Test A.
This result shows that the re-assignment operations of string variables within the method do not have any effect on the prototype of the variable. Well, the logic and the results of this example are all clear, and then we'll analyze this little program. Before that, let's review the so-called "pass-through" and "pass-references" issues in Java.
Two, "Pass value" and "pass reference" problem in Java
Many novice Java programmers are thinking about this issue because it is the so-called "C-language value and pass-pointer problem" in the Java language similar performance.
The final conclusion is:
In Java, when a base type is passed as a parameter to a method, no matter how the parameter is changed within the method, the external variable prototype is always the same, and the code resembles the example above:
int number = 0;
ChangeNumber (number) {number++}; Change the int variable sent
SYSTEM.OUT.PRINTLN (number); Then number is still 0.
This is called "value transfer", where the method operates on a parameter variable (that is, a copy of a value of a prototype variable) that changes only one copy of the prototype variable, not the variable itself. So the variable prototypes don't change.
However, when a method passes in a parameter that is not a base type (that is, a variable of an object type), the method changes the parameter variable while the variable prototype changes, and the code is similar to the example above:
StringBuffer strbuf = new StringBuffer ("original");
Changestringbuffer (strbuf) {strbuf.apend ("is changed!")}//change sent StringBuffer variable
System.out.println (STRBUF); Then the value of the strbuf becomes the original is changed!
This feature is called "Reference passing", also known as a pass-by, in which a method operates a parameter variable by copying a reference to the variable, and then by referencing the true address of the variable (here is the object) and manipulating it. When the method is finished, the parameter variable inside the method disappears. But to know that this variable is just a reference to an object, it simply points to the real address of the object, not the object itself, so its disappearance does not have any negative impact. Looking back at the prototype variable, the prototype variable is essentially a reference to that object (and the parameter variable is the same), and the change to the object of the parameter variable is simply the change to the object that the prototype variable refers to. So the object represented by the prototype variable is changed, and the change is preserved.
Knowing this classic question, many attentive readers will immediately ask a new question: "But the string type is a non basic type in the Java language!" Why it has not been preserved in the method of change! "Indeed, this is a problem, and this new question almost overturns all the conclusions of that classic question." Is that so? OK, now let's continue with the analysis.
Third, one of the distortions of string parameter transfer --direct assignment and object assignment
How does a variable of type string, as a parameter, be passed as a value in the same way as a basic type variable? Some friends have explained the problem, but unfortunately it is not correct.
One explanation is that if you assign a value to a string of a variable without a new object, instead of assigning it directly to a string, Java treats this string variable as the basic type. That is, you should string str = new String ("original"), rather than string str = "original";. Is that the problem? Let's do a little makeover for the previous example and see what happens after we run it. The modified code is as follows:
private void Testb () {
string originalstr = new String ("original");
System.out.println ("Test B Begin:");
SYSTEM.OUT.PRINTLN ("The outer String:" + originalstr);
Changenewstring (ORIGINALSTR);
SYSTEM.OUT.PRINTLN ("The outer String after inner change:" + originalstr);
System.out.println ("Test B End:");
System.out.println ();
}
public void Changenewstring (String original) {
original = new String (original + ' is changed! ');
System.out.println ("The changed inner String:" + original);
}
Let's take a look at the results of this operation:
Test B Begin: The
outer string:original the
changed inner string:original is changed!
The outer String after inner change:original
Test B-end.
Practice has proved that this statement is wrong.
In fact, the difference between the direct assignment of a string and the assignment of a new object is only in different ways of storing it.
Under Simple description:
When a string is directly assigned, a variable of type string refers to a value that is stored in a constant pool of the class. Because the original itself is a string constant, and on the other hand a string is an immutable type, the variable of this string is equivalent to a reference to a constant. In this case, the size of the variable's memory space is determined at compile time.
The new object is to store the original in the memory space of the string object, and the storage action is performed at run time. In this case, Java does not treat the original string as a constant because it appears as a parameter to create a string object.
Therefore, there is no direct connection between the assignment of string and its parameter-passing problem. In short, this explanation is not a positive solution.
Iv. on the distortion of string parameter transfer problem --"=" Variable value and method variable value
Some friends think that the problem of the variable value is in the way of changing the value.
This argument says: "In Java, there are two conditions for changing the value of a parameter, the first of which is to assign a value using the assignment number" = "to make it change; the second, for reference to some objects, changes their member data in a certain way, as through the object's own method. For the first case, the change does not affect data other than the method passed into the parameter variable, or directly to the source data. The second method, on the other hand, affects the source data-because the reference indicates that the object has not changed, and the change to its member data is essentially the changed object. ”
This way sounds like some ..., we still use the old method, write demo, do a small test, the code is as follows:
private void Testc () {
string originalstr = new String ("original");
System.out.println ("Test C Begin:");
SYSTEM.OUT.PRINTLN ("The outer String:" + originalstr);
Changestrwithmethod (ORIGINALSTR);
SYSTEM.OUT.PRINTLN ("The outer String after inner change:" + originalstr);
System.out.println ("Test C end.");
System.out.println ();
}
private static void Changestrwithmethod (String original) {
original = Original.concat ("is changed!");
System.out.println ("The changed inner String:" + original);
}
The results are as follows:
Test C Begin: The
outer string:original the
changed inner string:original is changed!
The outer String after inner change:original
Test C-end.
Well, this proves that the problem is not here, yet another explanation died out under the practical argument.
So what is the reason for this situation?
OK, no suspense, the following is my explanation.
The crux of string parameter transfer problem
In fact, the most direct way to really understand a class or an API framework is to look at the source.
Let's take a look at that little piece of code (in the String Class) of the new string object, which is the constructor of the string class:
public string (string original) {int size = Original.count;
char[] OriginalValue = Original.value;
Char[] v; if (originalvalue.length > Size) {//the array representing the String is bigger than the new// String itself.
Perhaps this constructor are being called//in order to trim the baggage, so make a copy of the array.
int off = Original.offset;
v = arrays.copyofrange (OriginalValue, off, off+size); } else {//the array representing the same//size as the string, so no point in Maki
ng a copy.
v = originalvalue;
} this.offset = 0;
This.count = size;
This.value = v; }
You may have noticed the char[inside], which means that storage of string is actually implemented through char[]. What do you think? is actually a layer of window paper. I wonder if you remember the basic types of wrapper classes defined in the Java API. For example, the integer is int packing class, float is float the packing class and so on. The value operations of these wrapper classes are actually implemented by their corresponding base type operations. Are you feeling something? Yes, string is equivalent to the wrapper class of char[]. One of the characteristics of the wrapper class is that it reflects the nature of its corresponding basic type in the operation of its value. This is how the wrapper class manifests when the parameter is passed. Therefore, the explanation of the result of string in this case is natural. Similarly, Integer, float and other packaging classes and string in this case the performance is the same, the specific analysis is omitted here, interested friends can do their own experiments.
This is why when manipulating strings is implemented in different ways, the real reason for using StringBuffer is recommended. As for StringBuffer why not show a string this phenomenon, we look at the realization of the stringbuffer will understand, here also no longer repeat.
Six, write in the last
The principle of passing a parameter of this string type is also shown. In fact, we can see that, as long as the analysis method is correct, thinking finally come to the correct conclusion.
The basis of the correct analysis method is two:
1, more practice: Do not make a hand lazy, practice will be true.
2, based on the principle: the most straightforward way to understand the logic of the program is to look at the source code, this is beyond doubt.
As long as based on these two basic analysis, in many cases will achieve a multiplier effect. This is a form of experience, but also is one of the "shortcut" Ways of analyzing the program.