按值传递(StringBuilder 与 String)
Pass-by-value (StringBuilder vs String)
我不明白为什么 System.out.println(name) 输出 Sam 而不受方法的 concat 函数的影响,而System.out.println(names) 输出 Sam4 作为方法的附加方法的结果。为什么受影响的是 StringBuilder 而不是 String?通常,对对象引用的调用方法会影响调用者,所以我不明白为什么 String 结果保持不变。提前致谢
public static String speak(String name) {
name = name.concat("4");
return name;
}
public static StringBuilder test(StringBuilder names) {
names = names.append("4");
return names;
}
public static void main(String[] args) {
String name = "Sam";
speak(name);
System.out.println(name); //Sam
StringBuilder names = new StringBuilder("Sam");
test(names);
System.out.println(names); //Sam4
}
因为当你打电话给 speak(name);
时,当你打电话时里面会说话
name = name.concat("4");
它创建了一个新对象,因为 String
s 是不可变的。当您更改原始字符串时,它会创建一个新对象,我同意您返回它但您没有捕获它。
所以基本上你正在做的是:
name(new) = name(original) + '4'; // but you should notice that both the names are different objects.
尝试
String name = "Sam";
name = speak(name);
当然现在我认为没有必要解释为什么它与 StringBuilder
一起工作,除非你不知道 StringBuilder
是可变的。
当您调用 speak(name)
时,它会计算新值,但会丢弃它。
如果将其替换为
name = speak(name);
结果将如您所愿。
使用 StringBuilder
,您传递的对象是可变的:所以
names.append(names);
更改当前对象的状态(它也是 returns 对同一对象的引用,这只是一种方便,允许您编写 names.append(...).append(...)
等代码)。因此,在 StringBuilder
的情况下,您在调用该方法时引用的对象实际上已经更改,因此您会看到更改。
字符串
String is immutable ( once created can not be changed )object . The
object created as a String is stored in the Constant String Pool .
Every immutable object in Java is thread safe ,that implies String is
also thread safe . String can not be used by two threads
simultaneously. String once assigned can not be changed.
String demo = " hello " ; // The above object is stored in constant
string pool and its value can not be modified.
demo="Bye" ; //new "Bye" string is created in constant pool and
referenced by the demo variable // "hello" string still
exists in string constant pool and its value is not overrided but we
lost reference to the "hello"string
StringBuilder
StringBuilder is same as the StringBuffer , that is it stores the
object in heap and it can also be modified . The main difference
between the StringBuffer and StringBuilder is that StringBuilder is
also not thread safe. StringBuilder is fast as it is not thread safe
.
有关详细信息,请查看 this
结论:
您不需要再次将值重新分配给 StringBuilder
因为它已经是一个参考
测试方法应该是
public static void test(StringBuilder names) {
names.append("4");
}
但说话应该是
String name = "Sam";
name = speak(name);
String
在 java 中是不可变的。只要您在名称上调用 concat
方法。创建了一个新字符串,当您在 System.out.println(name)
中使用旧引用时。如果您想使用修改后的字符串,您应该明确 return 引用。
虽然 StringBuilder
是可变的,但它 return 始终是相同的引用。
看Javadoc for String
,会读到
[...] String objects are immutable [...].
这意味着concat(String)
不会改变String
本身,而是构造一个新的String
。
StringBuilder
s, on the other hand, are mutable. By calling append(CharSequence)
,对象本身发生变异
因为 String
是不可变的,因此 String#concat
不会修改原始的 String 实例,它只会 returns 一个新的 String
而原始的保持不变,而StringBuilder
是可变的,变化反映在作为参数传递的 StringBuilder
实例中。
在你的方法speak
中,concat
方法return是一个new String,调用它的原始对象没有改变(字符串是不可变的)。如文件所示:
If the length of the argument string is 0
, then this String
object is returned. Otherwise, a String
object is returned that represents a character sequence that is the concatenation of the character sequence represented by this String
object and the character sequence represented by the argument string.
调用name.concat("4")
等同于name + "4"
。
在您的 test
方法中,append
方法 修改了 StringBuilder
的内容 。如文件所示:
The principal operations on a StringBuilder
are the append
and insert
methods, which are overloaded so as to accept data of any type. Each effectively converts a given datum to a string and then appends or inserts the characters of that string to the string builder. The append
method always adds these characters at the end of the builder; the insert
method adds the characters at a specified point.
在您的主要方法中,name
和 names
仍然是 与方法调用之前相同的 对象,但是 [=26= 的内容] 未更改,因为字符串是不可变的,而 names
的内容已更改。
如果您使用这两种方法的 return 值,那么您会得到预期的结果。
好的,speak
方法在做什么?
首先,
name.concat("4");
创建新对象,等于 name
,与 "4"
连接。
所以,行
name = name.concat(4);
重新定义local(对于speak
方法)变量name
.
然后你return用
引用这个新值
return name;
所以,在方法中传递的原始变量没有被修改,但是方法return修改了值。
在 test
方法中,您实际上修改了变量而不修改引用(StringBuilder
class 是可变的,因此如果可以修改此类型,则为变量)。
然后我们可以看到另一个问题出现:为什么 StringBuilder.append
return 的值,它似乎是多余的。这个问题的答案在于"builder"模式的描述,这是实现修改方法的通常方式。参见 wikipedia on Builder pattern。
首先,String
是Java中的不可变class。一个 不可变的 class 只是一个 class 的实例不能被修改。实例中的所有信息在实例创建时就已经初始化,不可修改。
其次,在 java 中,参数是按值而不是按引用发送的。
在您的方法 'test' 中,您不需要 names = names.append("4")
,names.append("4")
就足够了。
如果你检查 java docs 的 String 对象,你会看到那里的大多数方法,包括 concat,都会生成一个新的 String .
所以要在输出 Sam4 上也为字符串,您需要在 main 方法中有这个 name = speak(name)
.
我不明白为什么 System.out.println(name) 输出 Sam 而不受方法的 concat 函数的影响,而System.out.println(names) 输出 Sam4 作为方法的附加方法的结果。为什么受影响的是 StringBuilder 而不是 String?通常,对对象引用的调用方法会影响调用者,所以我不明白为什么 String 结果保持不变。提前致谢
public static String speak(String name) {
name = name.concat("4");
return name;
}
public static StringBuilder test(StringBuilder names) {
names = names.append("4");
return names;
}
public static void main(String[] args) {
String name = "Sam";
speak(name);
System.out.println(name); //Sam
StringBuilder names = new StringBuilder("Sam");
test(names);
System.out.println(names); //Sam4
}
因为当你打电话给 speak(name);
时,当你打电话时里面会说话
name = name.concat("4");
它创建了一个新对象,因为 String
s 是不可变的。当您更改原始字符串时,它会创建一个新对象,我同意您返回它但您没有捕获它。
所以基本上你正在做的是:
name(new) = name(original) + '4'; // but you should notice that both the names are different objects.
尝试
String name = "Sam";
name = speak(name);
当然现在我认为没有必要解释为什么它与 StringBuilder
一起工作,除非你不知道 StringBuilder
是可变的。
当您调用 speak(name)
时,它会计算新值,但会丢弃它。
如果将其替换为
name = speak(name);
结果将如您所愿。
使用 StringBuilder
,您传递的对象是可变的:所以
names.append(names);
更改当前对象的状态(它也是 returns 对同一对象的引用,这只是一种方便,允许您编写 names.append(...).append(...)
等代码)。因此,在 StringBuilder
的情况下,您在调用该方法时引用的对象实际上已经更改,因此您会看到更改。
字符串
String is immutable ( once created can not be changed )object . The object created as a String is stored in the Constant String Pool . Every immutable object in Java is thread safe ,that implies String is also thread safe . String can not be used by two threads simultaneously. String once assigned can not be changed.
String demo = " hello " ; // The above object is stored in constant string pool and its value can not be modified.
demo="Bye" ; //new "Bye" string is created in constant pool and referenced by the demo variable // "hello" string still exists in string constant pool and its value is not overrided but we lost reference to the "hello"string
StringBuilder
StringBuilder is same as the StringBuffer , that is it stores the object in heap and it can also be modified . The main difference between the StringBuffer and StringBuilder is that StringBuilder is also not thread safe. StringBuilder is fast as it is not thread safe .
有关详细信息,请查看 this
结论:
您不需要再次将值重新分配给 StringBuilder
因为它已经是一个参考
测试方法应该是
public static void test(StringBuilder names) {
names.append("4");
}
但说话应该是
String name = "Sam";
name = speak(name);
String
在 java 中是不可变的。只要您在名称上调用 concat
方法。创建了一个新字符串,当您在 System.out.println(name)
中使用旧引用时。如果您想使用修改后的字符串,您应该明确 return 引用。
虽然 StringBuilder
是可变的,但它 return 始终是相同的引用。
看Javadoc for String
,会读到
[...] String objects are immutable [...].
这意味着concat(String)
不会改变String
本身,而是构造一个新的String
。
StringBuilder
s, on the other hand, are mutable. By calling append(CharSequence)
,对象本身发生变异
因为 String
是不可变的,因此 String#concat
不会修改原始的 String 实例,它只会 returns 一个新的 String
而原始的保持不变,而StringBuilder
是可变的,变化反映在作为参数传递的 StringBuilder
实例中。
在你的方法speak
中,concat
方法return是一个new String,调用它的原始对象没有改变(字符串是不可变的)。如文件所示:
If the length of the argument string is
0
, then thisString
object is returned. Otherwise, aString
object is returned that represents a character sequence that is the concatenation of the character sequence represented by thisString
object and the character sequence represented by the argument string.
调用name.concat("4")
等同于name + "4"
。
在您的 test
方法中,append
方法 修改了 StringBuilder
的内容 。如文件所示:
The principal operations on a
StringBuilder
are theappend
andinsert
methods, which are overloaded so as to accept data of any type. Each effectively converts a given datum to a string and then appends or inserts the characters of that string to the string builder. Theappend
method always adds these characters at the end of the builder; theinsert
method adds the characters at a specified point.
在您的主要方法中,name
和 names
仍然是 与方法调用之前相同的 对象,但是 [=26= 的内容] 未更改,因为字符串是不可变的,而 names
的内容已更改。
如果您使用这两种方法的 return 值,那么您会得到预期的结果。
好的,speak
方法在做什么?
首先,
name.concat("4");
创建新对象,等于 name
,与 "4"
连接。
所以,行
name = name.concat(4);
重新定义local(对于speak
方法)变量name
.
然后你return用
引用这个新值return name;
所以,在方法中传递的原始变量没有被修改,但是方法return修改了值。
在 test
方法中,您实际上修改了变量而不修改引用(StringBuilder
class 是可变的,因此如果可以修改此类型,则为变量)。
然后我们可以看到另一个问题出现:为什么 StringBuilder.append
return 的值,它似乎是多余的。这个问题的答案在于"builder"模式的描述,这是实现修改方法的通常方式。参见 wikipedia on Builder pattern。
首先,String
是Java中的不可变class。一个 不可变的 class 只是一个 class 的实例不能被修改。实例中的所有信息在实例创建时就已经初始化,不可修改。
其次,在 java 中,参数是按值而不是按引用发送的。
在您的方法 'test' 中,您不需要 names = names.append("4")
,names.append("4")
就足够了。
如果你检查 java docs 的 String 对象,你会看到那里的大多数方法,包括 concat,都会生成一个新的 String .
所以要在输出 Sam4 上也为字符串,您需要在 main 方法中有这个 name = speak(name)
.