本问题已经有最佳答案,请猛点这里访问。
我不明白为什么system.out.println(name)在不受方法的concat函数影响的情况下输出sam,而system.out.println(name)在方法的append方法的结果下输出sam4。为什么StringBuilder受到影响而不是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);的时候,当你打电话给speak(name);的时候,内部会说话。
name = name.concat("4");
它创建了一个新对象,因为String是不可变的。当您更改原始字符串时,它将创建一个新对象,我同意您返回它,但您没有捕获它。
所以本质上你所做的是:
name(new) = name(original) + '4'; // but you should notice that both the names are different objects.
尝试
String name ="Sam";
name = speak(name);
当然,现在我认为没有必要解释为什么它与StringBuilder一起工作,除非你不知道StringBuilder是可变的。
"它创建了一个新对象,因为字符串是不可变的。"在语言中没有"可变"的概念。它返回一个新的对象,因为这就是该方法的文档所要做的。它不会修改它所调用的对象,同样,因为这就是该方法的文档所要做的。
@很抱歉,先生,我肯定我没有你知道的那么多,但是我想如果我说"它返回一个新对象,因为它的方法被记录下来了",OP会不高兴的。所以这就是为什么我想给出一些背后的理由。
但是我们只说类是"不可变的",因为它的所有方法都被记录为不修改它。所以说方法不修改它是循环推理,因为它是不可变的。
@纽阿克特可能是"鸡还是蛋":p
看看JavaDoc for String,你会发现
[...] String objects are immutable [...].
这意味着concat(String)并没有改变String本身,而是构建了一个新的String。
另一方面,StringBuilders是可变的。通过调用append(CharSequence),对象本身就发生了变化。
好的,speak方法在做什么?
首先,
name.concat("4");
创建新对象,该对象等于name,与"4"连接。
所以,这条线
name = name.concat(4);
重新定义局部(用于speak方法)变量name。
然后返回对这个新值的引用
return name;
因此,方法中传递的原始变量不会被修改,但该方法返回修改后的值。
在test方法中,实际上修改变量而不修改引用(StringBuilder类是可变的,因此如果可以修改此类型,则是可变的)。
然后我们可以看到另一个问题出现了:为什么StringBuilder.append返回值,而这个值似乎是多余的。这个问题的答案在于对"构建器"模式的描述,这是实现修改方法的常用方法。参见维基百科的建设者模式。
在方法speak中,concat方法返回一个新字符串,它调用的原始对象不变(字符串是不可变的)。如文件所示:
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仍然是方法调用之前的同一对象,但name的内容不变,因为字符串是不可变的,而names的内容已更改。
如果您使用了这两个方法的返回值,那么您将得到预期的结果。
由于String是不可变的,因此String#concat不修改原来的字符串实例,它只返回一个新的String,而原来的则保持不变,而StringBuilder是可变的,其变化反映在作为参数传递的StringBuilder实例中。
在Java中,EDCOX1的1Ω是不可变的。一旦对名称调用concat方法。将创建一个新字符串,当您在System.out.println(name)中使用旧的引用时。如果要使用修改后的字符串,应显式返回引用。虽然StringBuilder是可变的,它总是返回相同的引用。
当调用speak(name)时,它计算新值,但丢弃它。
如果你把它换成
name = speak(name);
结果就是你所期望的。
使用StringBuilder时,您传递的对象是可变的:所以
names.append(names);
更改当前对象的状态(它还返回对同一对象的引用,这只是方便您编写代码,如names.append(...).append(...)等)。因此,在StringBuilder的情况下,调用方法时所引用的对象实际上已经更改,因此您可以看到更改。
您没有回答这个问题:为什么它与StringBuilder一起工作?
是的,是真的。参见更新。
首先,EDCOX1×0是Java中不可变的类。不可变类只是不能修改其实例的类。实例中的所有信息在创建实例时初始化,不能修改。
第二,Java参数是通过值发送的,而不是通过引用发送的。
在你的"测试"方法中,你不需要names = names.append("4"),相反,names.append("4")就足够了。
如果您检查Java对象的字符串对象,您将看到其中的大多数方法,包括CONTAT,将生成一个新的字符串。
因此,要让输出sam4也用于字符串,您需要在主方法中使用这个name = speak(name)。
弦
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 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
.
有关详细信息,请检查此
结论:您不需要再将该值重新分配给StringBuilder,因为它已经是一个引用测试方法应为
public static void test(StringBuilder names) {
names.append("4");
}
但说话应该是
String name ="Sam";
name = speak(name);
这不是被问到的问题。
好的,我更新了答案