How do String objects work (like immutable objects)?
I have these two situations:
String s = "aa";
s = s + " aa";
System.out.println(s);
//......
that work fine! It prints aa aa. But there is a problem:
String s = "aa";
this.addStringToStatement(s开发者_如何学Python, " aa");
System.out.println(s);
//...
private void addStringToStatement(String statement, Object value) {
statement += value;
}
It prints: aa. What is the reason?? Thanks!
There are two issues to understand here.
The String append operator will create a new immutable String object. The expression
s + value
is a different object in memory froms
.In your function
addStringToStatement
when you execute statement += value;
you aren't changing the value of the variables
, rather you are reassigning the local pointerstatement
to a new String instance.
EDIT: Fixed usual noob mistake: In Java, object references are passed, not the objects themselves.
This is because in Java a reference is passed by value. Here when you passed s and " aa" as two parameters.
In the method statement variable (which has reference of s) is altered to point to something else ie "aa aa". Note only the statement reference is passed, s is still pointing to "aa".
So when you print s you get what is expected :)
this is because of how passing by value works in Java, you need to do something like this:
String s = "aa";
s = this.addStringToStatement(s, " aa");
System.out.println(s);
//...
private string addStringToStatement(String statement, Object value) {
statement += value;
return statement;
}
Strings in Java are immutable. If you have a String s="aa", you only have a reference to the String "aa" inside the JVM. If you want the String "aa aa" assigned to s, you assign only the reference (address) to "aa aa" (another String inside the JVM) to s, "aa" lurks still somewhere in the JVM.
The statement "Java references are passed by value" is somewhat confusing (if true). If you use a StringBuilder sb and give this StringBuilder to a function, the reference is "copied" but still points to the same object as sb:
public static void main(String[] args) {
final StringBuilder sb = new StringBuilder();
f(sb);
System.out.println(sb);
}
private static void f(final StringBuilder sb) {
sb.append("aa aa");
}
You have to return the "statement" variable. Without the "this.*" part.
String s = "aa";
s = addStringToStatement(s, " aa");
System.out.println(s);
//...
private String addStringToStatement(String statement, Object value) {
statement += value;
return statement;
}
@Frank Meißner (new to this, can't reply to answers yet)
Just to clarify the difference between String and StringBuilder (in case anyone reading this is confused), while both store the CharSequence they hold as a char[], the char[] within String cannot be changed, thus a new String has to be created for every alteration. In the case of a StringBuilder, there are methods like StringBuilder.append(String) that can change the internal char[] of the StringBuilder, so if StringBuilder.append(String) is called, no new object will have to be created for the content of the StringBuilder to change.
As per Frank Meißner's example, System.out.println(sb); will print "aa aa", since the method append(String) was called on the StringBuilder sb. final doesn't hurt here since the identity of sb isn't changed, only its state.
+= in case of string doesn't modify string itself but produce new string. in case of your method you set this new string reference to local variable (parameter)
Java references are passed by value. When you pass a String
to a method and it changes inside it points to different String
. You can either return the String
after appending or use StringBuffer
as argument.
精彩评论