该帖已经被评为新手帖
|
|
---|---|
作者 | 正文 |
发表时间:2008-09-04
Eastsun 写道 归根究底,其实就是一个对“按引用传递”这个概念理解的问题。
如果你非得说“按引用传递”,那么得重新定义一个与C++中“按引用传递”不同的概念出来。 从说法上来说,THE Java™ Programming Language, Fourth Edition All parameters to methods are passed "by value." Some people will say incorrectly that objects are passed "by reference." In programming language design, the term pass by reference properly means that when an argument is passed to a function, the invoked function gets a reference to the original value, not a copy of its value. If the function modifies its parameter, the value in the calling code will be changed because the argument and parameter use the same slot in memory.The Java programming language does not pass objects by reference; it passes object references by value. Because two copies of the same reference refer to the same actual object, changes made through one reference variable are visible through the other. There is exactly one parameter passing modepass by valueand that helps keep things simple. 这里对程序设计语言中的术语pass by reference 有明确的解释。 但我感觉出问题的源头还是java对引用的定义,引用在C++中已经有明确的意义了,而java为了避免指针的说法采用了引用,不过这种引用其实就是一种指针,在c++中,引用就是别名,而java不是。从方法调用来看,对于引用类型参数来说,和C/C++中的传指针是类似的,你可以修改指针指向的内容,但是你修改了指针本身的值的话就没什么效果了。 看这个例子: #include <iostream> using namespace std; class Test { public: int a; }; void change(Test* test){ test->a=5; test=new Test(); test->a=8; } int main() { Test* t=new Test(); change(t); cout<<t->a<<endl; } 但是和C++的引用传递就明显不同了。这就不用举例了。 最后我感觉,java的设计者们改变了reference的语义,为了方法传参模型的简单,又只定义了一个值传递的模式。没有定义新的pass by reference 的语义,这才导致了这种争论。 |
|
返回顶楼 | |
发表时间:2008-10-17
C代码
Type var1 = ...; Type var2 = ...; swap(var1,var2); 这里定义的两个对象就是引用 指向内存中存储数据的地址 C代码 swap(Type arg1, Type arg2) { Type temp = arg1; arg1 = arg2; arg2 = temp; } 而在这块实际上arg1,arg2是两个新的引用也是指向内存中存储数据的地址 当你做交换的时候 实际交换arg1和arg2两个引用 就是将arg1的引用指像arg2引用所指像的地址而arg2引用指向arg1的地址,,,而不会改变内存中数据存储的地址, 而var1和var2的引用的并没有被改变,,,还是指像原本的地址 。。。 这就是java的引用传递和C++引用传递的区别。。。。。C++传递会改变内存地址中的数据存储位置 和JAVA不会 它只会改变对象引用的指向 而不会更改内趣中地址所存储的数据 |
|
返回顶楼 | |
发表时间:2008-10-17
无聊的争论
|
|
返回顶楼 | |
发表时间:2008-10-17
其实数组还是引用,说泛一点变量都是引用,只不过是被隐藏了
|
|
返回顶楼 | |
发表时间:2008-10-17
一开始被你的一句话给吓到了,其实说到底,我们都是动物,,是和这个道理一样吧~~~~ 我不同意你的看法~~不好意思,不支持你。
|
|
返回顶楼 | |
发表时间:2008-10-19
其实传的是什么关键是看个人的理解了。。不管怎么样只要结果是对的就好。。我个人的理解是在这个传递过程中存在的都是值传递。。及传递的都是变量本身的值。基本数据类型传的就是本身那个值。引用类型的是Object中toString()打印出的值。对象本身的值是在保存在内存的堆里面的。不会随便把整个值进行交换的。。交换的是保持在内存中栈中的引用的值。。其实那些觉得是交换了对象本身的值的可以很简单的就验证出来的。。你定义两个引用指向同一个对象。然后在那另外一个对象的引用与这其中的一个进行交换。。然后打印出那个没参与交换的引用指向那个对象的值就很清楚了!
|
|
返回顶楼 | |
发表时间:2008-12-01
MarkDong 写道 楼主的说法有点儿牵强,所有的调用都是按值传递这是没错的,因为调用堆栈的原理限定了我们只能将各种值压入堆栈,而方法返回时,并不会将堆栈中的值再进行处理,而只是简单的调整栈顶指针将原先压入堆栈的值废弃掉。所以,一切对压栈而传递到方法体内的参数,方法内部所做的修改对外界都是无法看到的。
那么鉴于这种情况,为了将函数内部对参数的修改可以带到函数外,各种语言做了不同的处理,C/C++中可以传递指针,而Java则默认传递对象的引用。如果楼主非要把方法调用时压入堆栈的地址称为值的话,其实也并非不可,只不过这种说法我觉得有点儿牵强了。 正解 ![]() |
|
返回顶楼 | |
发表时间:2009-01-11
如果传的是基本数据类型,修改这个值并不会影响作为参数传进来的那个变量,因为你修改的是方法的局部变量,是一个副本。
如果传的是一个对象的引用,也是一样的,也是一个副本,但是这个副本和作为参数传进来的那个引用指向的是内存中的同一个对象,所以你通过这个副本也可以操作那个对象。但是如果你修改这个引用本身,比如让他指向内存中的另外一个对象,原来作为参数传进来的那个引用不会受到影响。 我觉得弄明白这些就行了,说值传递或引用传递都无所谓,但是说值传递更适合一些,这个值可以是引用也可以是基本数据类型。 --------- 引用他人的话 所有的调用都是按值传递这是没错的,因为调用堆栈的原理限定了我们只能将各种值压入堆栈,而方法返回时,并不会将堆栈中的值再进行处理,而只是简单的调整栈顶指针将原先压入堆栈的值废弃掉。所以,一切对压栈而传递到方法体内的参数,方法内部所做的修改对外界都是无法看到的。那么鉴于这种情况,为了将函数内部对参数的修改可以带到函数外,各种语言做了不同的处理,C/C++中可以传递指针,而Java则默认传递对象的引用。如果楼主非要把方法调用时压入堆栈的地址称为值的话,其实也并非不可,只不过这种说法我觉得有点儿牵强了。 --------- 引用他人的话 同意两位的意见!谢谢 |
|
返回顶楼 | |
发表时间:2009-01-11
最后修改:2009-01-11
基础类型, string是值传递。 不过, string比较特别。
其他所有继承Object对象的东西, 都是引用。 因为JAVA实际上, 说的不好听点, 任意时刻任何实例都是全JVM可见的,不然GC就管理不到它了, 看你用角度看这个理解。 整天不F规范上说的人还真不少。 别总觉得E文的技术文章就是真理哦。 |
|
返回顶楼 | |
发表时间:2009-01-11
我觉得这个讨论没有多大意义,大家都知道怎么用而且能够达成共识也就可以了,如果真的要讨论的话,LZ说的这种C++中的按引用传递还不如叫按指针传递,因为C/C++中任何类型包括(指针类型在内)都可以再定义一个指针指向该数据,才会出现这种“按指针传递”的方式,Java这种没有指针类型的语言当然不会有这种“按指针传递”,但是Java中的对象确实存在一个引用,说他是按引用传递也没什么错误,干吗非要扯的那么清楚呢,我觉得LZ和LZ引用的那篇文章的作者的想法,是对“按引用传递”的一种曲解 |
|
返回顶楼 | |