一道JAVA 考试题 请高手指点

在amay的scjp试题中有这样一道题目:

Click the exhibit button:
1. public class test {
2. public static void stringReplace (String text) {
3. text = text.replace (‘j’ , ‘i’);
4. }
5.
6. public static void bufferReplace (StringBuffer text) {
7. text = text.append (“C”)
8. }
9.
10. public static void main (String args[]) {
11. String textString = new String (“java”);
12. StringBuffer textBuffer = new StringBuffer (“java”);
13.
14. stringReplace (textString);
15. bufferReplace (textBuffer);
16.
17. System.out.println (textString + textBuffer);
18. }
19. }
What is the output

答案是javajavaC,我不清楚为什么textString的内容没有改变而textBuffer的内容改变了,我是菜鸟弄不明白阿

请高手指点谢谢了

faint,我也不懂,与静态方法有关系?期盼有高手就这一方面做一解答

String 是创建了就不会改变了,可以理解成一个常量。
虽然你是用replace去改变了,但他本身并没改变,除非你定义另一个String去接受结果,而开始的那个String是不会有任何变化的
而StringBuffer却是可以变的。

这样理解吧:
基本类型的变量在传递时不会改变自身的值,比如:int,double,String
对象类型的变量在传递时会改变自身的值,比如:StringBuffer、Integer

不知道这样口语化的说法是否有证明力?

text = text.append (“C”)
这样理解
StringBuffer temp = text.append("C");//1
text = temp;//2

这个地方 1改变了实参的值
而2对形参的引用修改不会修改temp指向的内存区域值

首先谢谢大家!
不知道我的理解对不对请大家指点
bufferReplace(textBuffer); 传到方法中的是句柄
而在
public static void stringReplace(String text) {
text = text.replace('j','i');
}
方法中只是对一块新的内存空间进行修改,也就是说它只传过来的是值
对吗?

public class Test {
public static void main(String args[]) {
String textString = new String("java");
StringBuffer textBuffer = new StringBuffer("java");
String text1 = textString;

text1 = text1.replace('j', 'i');
StringBuffer text = textBuffer;
text=text.append("C");

System.out.println(textString + textBuffer);
}

}

实际上楼主的程序等同上面的程序,其实
text1 = text1.replace('j', 'i');
text=text.append("C");
这两句完全可改成
text1.replace('j', 'i');
text.append("C");
只不过text1.replace('j', 'i');没有任何作用

public class Test {
public static void main(String args[]) {
String textString = new String("java");
StringBuffer textBuffer = new StringBuffer("java");
String text1 = textString;
text1 = text1.replace('j', 'i');

StringBuffer text2 = textBuffer;
text2=text2.append("C");

System.out.println(textString + textBuffer);
}

}

我来分析一下,首先String object属Immutable ones,所以String方法执行后返回的引用就不是以前的那个了,而StringBuffer不是这样,其方法操作的还是Heap中的那个对象,本题中最误导人的地方就是这句话“text = text.replace ('j' , 'i'); ”LH的text是一个新的String对象的reference,而这个ref是放在stack上的,但是这个stringReplace返回的同时又是一个void,所以这个ref就被discard掉了,到这里就很清楚了,从下面此类的汇编可以很清晰的看到这一切:

class Test extends java.lang.Object{
Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return

public static void stringReplace(java.lang.String);
Code:
0: aload_0
1: bipush 106
3: bipush 105
5: invokevirtual #2; //Method java/lang/String.replace:(CC)Ljava/lang/String;
8: astore_0
9: return

public static void bufferReplace(java.lang.StringBuffer);
Code:
0: aload_0
1: ldc #3; //String C
3: invokevirtual #4; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
6: astore_0
7: return

public static void main(java.lang.String[]);
Code:
0: new #5; //class String
3: dup
4: ldc #6; //String java
6: invokespecial #7; //Method java/lang/String."<init>":(Ljava/lang/String;)V
9: astore_1
10: new #8; //class StringBuffer
13: dup
14: ldc #6; //String java
16: invokespecial #9; //Method java/lang/StringBuffer."<init>":(Ljava/lang/String;)V
19: astore_2
20: aload_1
21: invokestatic #10; //Method stringReplace:(Ljava/lang/String;)V
24: aload_2
25: invokestatic #11; //Method bufferReplace:(Ljava/lang/StringBuffer;)V
28: getstatic #12; //Field java/lang/System.out:Ljava/io/PrintStream;
31: new #8; //class StringBuffer
34: dup
35: invokespecial #13; //Method java/lang/StringBuffer."<init>":()V
38: aload_1
39: invokevirtual #4; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
42: aload_2
43: invokevirtual #14; //Method java/lang/StringBuffer.append:(Ljava/lang/Object;)Ljava/lang/StringBuffer;
46: invokevirtual #15; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
49: invokevirtual #16; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
52: return

}

支持sparkstone的理解。
stringReplace中是新对象的reference,并且不再改变形参。

不必要搞那么复杂吧:
原则:
1,
String是一个不变对像
public final class String extends Object
2,
java中只有值传递,

stringReplace(String text)
中的text只是主函数中textString的一个copy
开始二者同时指象new String("java")这个对象

结果:
由于new String("java")这个对象是不可改变的
所以text.replace('j','i')反回的对象是用
new String("java")对象的"内容加以改变"构成的新String

以下是replace函数源码:

public String replace(char oldChar, char newChar) {
if (oldChar != newChar) {
int len = count;
int i = -1;
char[] val = value; /* avoid getfield opcode */
int off = offset; /* avoid getfield opcode */

while (++i < len) {
if (val[off + i] == oldChar) {
break;
}
}
if (i < len) {
char buf[] = new char[len];
for (int j = 0 ; j < i ; j++) {
buf[j] = val[off+j];
}
while (i < len) {
char c = val[off + i];
buf = (c == oldChar) ? newChar : c;
i++;
}
return new String(0, len, buf);
}
}
StringBuffer的append方法请加以观察

建议再碰到这种常用类使用问题时,先看源码,再发贴
养成习惯,会有好处的!