关于Java中的字符串不变性

St.*_*rio 4 java string

首先,我知道java中的字符串是不可变的.

我有一个关于String immutability的问题:

public static void stringReplace (String text) 
{
    text = text.replace ('j' , 'c'); /* Line 5 */
} 
public static void bufferReplace (StringBuffer text) 
{ 
    text = text.append ("c");  /* Line 9 */
} 
public static void main (String args[]) 
{ 
    String textString = new String ("java"); 
    StringBuffer textBuffer = new StringBuffer ("java"); /* Line 14 */
    stringReplace(textString); 
    bufferReplace(textBuffer); 
    System.out.println (textString + textBuffer); //Prints javajavac
} 
Run Code Online (Sandbox Code Playgroud)

但是如果我们写下以下内容:

public static void bufferReplace (StringBuffer text) 
{ 
    text = text.append ("c");  /* Line 9 */
} 
public static void main (String args[]) 
{ 
    String textString = new String ("java"); 
    StringBuffer textBuffer = new StringBuffer ("java"); /* Line 14 */
    textString = textString.replace ('j' , 'c');
    bufferReplace(textBuffer); 
    System.out.println (textString + textBuffer); //Prints cavajavac
} 
Run Code Online (Sandbox Code Playgroud)

事情是我预期第一个例子将打印与第二个打印相同.原因是当我们传递textString给函数时,我们实际传递了一个引用textString.现在在函数体另一个字符串是由生产text.replace ('j' , 'c'),我们分配给该字符串,我们在传递的字符串的参考.在第二个例子我刚分配到所产生的字符串的引用textString.replace ('j' , 'c');testString.为什么会有这么大的差异?

按照这个原因,结果必须相同.怎么了?

Era*_*ran 7

在第二个示例中textString = textString.replace ('j' , 'c');,在main方法中发生,因此为textString变量分配了一个new String,并String在打印输出时看到新值.

在第一个示例中,它不会发生,因为对stringReplace方法的调用不能更改String传递给它的引用.因此,您看到的输出就像您根本没有打过stringReplace(textString)电话一样.

这一切都归结为Java是一种价值传递语言.您无法更改传递给方法的Object引用,因为该引用是按值传递的.如果String不是不可变的,您可以通过调用改变其状态的String方法(如果存在这样的方法)来更改传递给方法的String实例,但是仍然无法为方法的参数分配新的String引用并看到它反映在该方法的调用者.

  • http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.1:*调用方法或构造函数时(第15.12节),实际的值参数表达式在执行方法或构造函数的主体之前初始化新创建的参数变量,每个声明的类型.*Java是按值传递的. (4认同)
  • @ St.Antario您没有改变传递给该方法的StringBuffer引用.如果您尝试将新StringBuffer分配给传递给该方法的变量,则结果将与接受String的方法相同.与StringBuffer的区别在于,您可以改变引用在方法内引用的对象. (2认同)
  • 不会.将StringBuilder的**引用**的副本生成并传递给该方法.因此,为引用分配新值不会更改原始值,但由于两个引用(原始和副本)都指向同一个对象,因此更改方法中对象的状态也会影响调用方法中的对象:涉及一个对象. (2认同)