精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2005-05-12
public class Pass { String a="123"; public static void test(Pass passA) { passA.a="abc"; } public static void main(String[] args) { Pass passB=new Pass(); passB.a= "123"; System.out.println(passB.a); test(passB); System.out.println(passB.a); } } 结果是: 123 abc 从这个结果来看是通过引用传递的.String不是简单类型,那么是不是也是通过引用来传递呢?看下面这个例子: public class Pass { public static void test(String str) { str = "World"; } public static void main(String[] args) { String string = "Hello"; System.out.println(string); test(string); System.out.println(string); } } 结果是: Hello Hello 第三个例子: public class Pass { public static void test(StringBuffer str) { str.append("World"); } public static void main(String[] args) { StringBuffer string = new StringBuffer("Hello"); System.out.println(string); test(string); System.out.println(string); } } 结果: Hello HelloWorld 这我就不太明白了,既然String不是简单类型,那么它应该和对象是一样通过引用来传递的,可是结果却相反.而StringBuffer却是通过引用来传递的? 这到底是为什么?哪位帮忙解释一下. 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2005-05-12
原来是学C++的么?
不要直接用书面上的引用的概念来套 Java中所有的变量都相当于C++中的基本类型变量(如int变量)以及指针变量 对于原生类型,就是传值了,没有什么可说的 对于你说的String以及StringBuffer,这两个都是类的变量就相当于指针了 在C/C++中 void fun(char * string);{ string="changed"; } void main(void);{ char * string="some text"; fun(string);; //string指向什么? } 至于StringBuffer则相当于 void fun(char * string);{ string[2]='c'; } void main(void);{ char * string="some text"; fun(string);; //string变了没? } Java中的“引用”是指非原生类型的变量的值保存的是对一个堆上对象的引用。 Java任何时候都是传值的,只不过该值的语义有所不同罢了 |
|
返回顶楼 | |
发表时间:2005-05-12
莫名其妙。现在的书 和 资料 怎么都是这样故意误导。在一些名词说法上绕圈子,而不从基本原理进行阐述。
“传值和传引用”这个问题,我已经看到在多个地方,提出过多次了。这个问题的出现频率这么高,不能怪读者,主要是“概念制造者”的错。 对于这个问题,如果学过汇编,那么就很容易从堆栈内存结构上理解。 http://dev.csdn.net/article/17/17286.shtm 所有的参数传递都是 传值,从来没有 传引用 这个事实。 所有的参数传递都会在 程序运行栈上 新分配一个 值 的复制品. 楼主的第一段代码。 public static void test(Pass passA); { passA.a="abc"; } 这个传的 PassA 的 地址值。这个 地址值 被复制了一份。 不信,你写: public static void test(Pass passA); { passA = null; } 看看, 对passA有什么影响? 毫无作用。函数调用出来后,passA还是原来的值,不会变成Null. 但是,你的代码对 passA进行了操作 passA.a ,改变了passA的成员变量。 这个成员变量是一个真实指向String 的 地址,当然能够被改变。 这就是操作 (.) 和 赋值 (=) 的区别。 这是对 成员变量 a 的 赋值。真正改变了成员变量 a 的值。 注意,这里传递的参数是 passA, 而不是 a. 所以,passA 被复制了一份。passA 的这个副本的 a 变量还 指向 原来的 passA 的 a 变量。 楼主后面的代码, public static void test(String str); { str = "World"; } 只有对参数的 赋值,没有对参数的操作,当然不会产生影响。 引用 public static void test(StringBuffer str) { str.append("World"); } 对参数进行了操作,当然会产生影响。 --- 另: 同意“厌倦发呆”的意见。 和我说的一个意思,只是表述重点有些区别。 --- 注: 传引用, 只有一种语法现象. 就是 C++的一种语法 void function(int & a){ a = 1; } 这个实际上编译为 void function(int * a){ *a = 1; } 还是传的 地址值。 |
|
返回顶楼 | |
发表时间:2005-05-12
传引用是没有错的,
public static void test(String str); { str = "World"; } 这里的str = "World" 的语义应该是新new String("world")对象,然后把str指向这个堆里面新增的"world"对象,已经不是传进来的"hello"引用了。 public static void test(String str); { String _str = str; str = "world"; System.out.println(_str);; System.out.println(str);; }可以验证 |
|
返回顶楼 | |
发表时间:2005-05-12
neooen 写道 传引用是没有错的,
public static void test(String str); { str = "World"; } 这里的str = "World" 的语义应该是新new String("world")对象,然后把str指向这个堆里面新增的"world"对象,已经不是传进来的"hello"引用了。 public static void test(String str); { String _str = str; str = "world"; System.out.println(_str);; System.out.println(str);; }可以验证 老兄你的引用观念跟我们差不过,但是不是楼主所理解的那种 C++的引用概念表现上可不是老兄说的这样亚 |
|
返回顶楼 | |
发表时间:2005-05-12
neooen 写道 传引用是没有错的,
public static void test(String str); { str = "World"; } 这里的str = "World" 的语义应该是新new String("world")对象,然后把str指向这个堆里面新增的"world"对象,已经不是传进来的"hello"引用了。 public static void test(String str); { String _str = str; str = "world"; System.out.println(_str);; System.out.println(str);; }可以验证 这个函数调用完了,出来之后呢? str 是 “hello”, 还是 “world” ? string str = "hello"; test( str );; // what is str now? print(str);; 这里的关键是,传递的参数的作用范围。 传递的参数“值” 会在 函数当前运行栈上 复制一份。所有的 操作和赋值 都是对那个 参数“值”副本 进行的。操作能够 改变成员变量,因为参数“值”副本 是一个 地址,能够正确指向成员变量的位置。而赋值 则根本没用,因为只是改变了当前函数栈内 参数“值”副本 的内容,而没有改变上一层函数栈内的 对应“值”。 |
|
返回顶楼 | |
发表时间:2005-05-12
j0hnny 写道 谢谢各位高人.我没有学过c++,只是偶然碰到这个问题.
我刚才问了一下我老师,他说这个问题不是值传递和引用传递的问题,而是因为String是不可以改的,而BufferString可以改. 我查了一下API,里面这样定义String: public final class String Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings. Because String objects are immutable they can be shared. 对于StringBuffer的说明: A string buffer implements a mutable sequence of characters. A string buffer is like a String, but can be modified. 应该可以作为正解吧? 我觉得所说的非原生类型的变量还是通过引用来传递的吧? 我是初学者,理解不对的地方请大家原谅,这里高手太多了. 你试试看这段代码。 public class Pass { public static void test(StringBuffer str); { str = new StringBuffer("World");; // = 赋值,而不是 append 操作 } public static void main(String[] args); { StringBuffer string = new StringBuffer("Hello");; System.out.println(string);; test(string);; System.out.println(string);; // what is it now ? } } 看看 string buffer 的值 会不会变? |
|
返回顶楼 | |
发表时间:2005-05-12
j0hnny 写道 谢谢各位高人.我没有学过c++,只是偶然碰到这个问题.
我刚才问了一下我老师,他说这个问题不是值传递和引用传递的问题,而是因为String是不可以改的,而BufferString可以改. 我查了一下API,里面这样定义String: public final class String Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings. Because String objects are immutable they can be shared. 对于StringBuffer的说明: A string buffer implements a mutable sequence of characters. A string buffer is like a String, but can be modified. 应该可以作为正解吧? 我觉得所说的非原生类型的变量还是通过引用来传递的吧? 我是初学者,理解不对的地方请大家原谅,这里高手太多了. kao,这家伙说话不厚道,你问的是传参的问题,不过这个问题不涉及到string能不能改啊,就是赋值的语义问题啊。stringbuffer是线程安全的可以修改,string线程不安全好象,所以讲their values cannot be changed 。出来混讲究厚道两字,最讨厌看到高手两字,大家重在交流嘛 |
|
返回顶楼 | |
发表时间:2005-05-12
kao 都是老问题了 前面很多的帖子都讨论过的,仔细看的话就会楼主就好明白啦
http://forum.iteye.com/viewtopic.php?t=11649 http://forum.iteye.com/viewtopic.php?t=12447 |
|
返回顶楼 | |
发表时间:2005-05-12
neooen 写道 j0hnny 写道 谢谢各位高人.我没有学过c++,只是偶然碰到这个问题.
我刚才问了一下我老师,他说这个问题不是值传递和引用传递的问题,而是因为String是不可以改的,而BufferString可以改. 我查了一下API,里面这样定义String: public final class String Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings. Because String objects are immutable they can be shared. 对于StringBuffer的说明: A string buffer implements a mutable sequence of characters. A string buffer is like a String, but can be modified. 应该可以作为正解吧? 我觉得所说的非原生类型的变量还是通过引用来传递的吧? 我是初学者,理解不对的地方请大家原谅,这里高手太多了. kao,这家伙说话不厚道,你问的是传参的问题,不过这个问题不涉及到string能不能改啊,就是赋值的语义问题啊。stringbuffer是线程安全的可以修改,string线程不安全好象,所以讲their values cannot be changed 。出来混讲究厚道两字,最讨厌看到高手两字,大家重在交流嘛 不是我不厚道,我确实问的是传参的问题,没有考虑到String是final的,当时没有想那么多,只是想弄明白是怎么回事。并不是通过这个混淆大家的思路,这个我也是后来才知道的。 |
|
返回顶楼 | |