用"堆栈区数据复制"理解Java赋值和参数传递机制的心得
2006-12-01 11:03
796 查看
[align=center]内容 [/align] 提纲: 1、版权声明 2、前言 3、正文 4、结论 5、附注 6、参考资料 =========================================================================================================================== 1、版权声明: 本文作者:littlebat,原始出处:用"堆栈区数据复制"理解Java赋值和参数传递机制的心得 (http://java.learndiary.com/disDiaryContentAction.do?goalID=2716),邮件:mdx-xx@tom.com。如有任何反馈意见请联系作者,作者会在本文原始出处随时更新此文。转载及引用请保留此版权声明,谢谢。 2、前言: 在所有一切之前,先让我们看一个例子,如果您能得出这个例子的正确答案,下面的内容您应该基本上领会了。当然,请注意,本文不光只是阐述Java方法的参数传递问题,站在一个统一的角度还包括Java的赋值操作。如果您有兴趣,不妨把它看完:) 例子1源码:Tester.java(摘改自:Java参数传递方式)
这里是标准答案: 问题1:primitive = 2 问题2:myClass仍然指向的是执行方法changeObject(MyClass)之前的Step 2的那个对象。 问题3:myClass.i = 3 您做对了吗(首先坦白,在写这篇文章之前,我得出了错误的答案:(,见:Java参数传递方式(转帖))?怎么,像我一样,没做对?那么您该好好读一下下面的内容了,读了之后还做不对的话就把我这篇帖子扔进垃圾堆吧。不过,扔之前能给我回复一下为什么我将感激不尽:) 3、正文: 关于Java的赋值和参数传递是按值(by value)进行的还是按引用(by reference)进行的,这个问题曾经迷惑了很多人,包括我。而且,我想,这个问题还将继续迷惑一些人,包括那些C++的高手。 在这里,我不准备用“按值(by value)”和“按引用(by value)”这样的术语来阐述这个问题。因为,从字面的理解来看,这样的术语在不同的人头脑里有不同的含义。我试图从Java数据(包括原始类型(primitive type)和对象(ojbect))在内存中的存储这个角度,用一个自创的“术语”来阐述我对这个问题的理解。这个术语就是:“堆栈区数据复制(Stack Data Copy,简称SDC)”。详细一点就是:在Java中,不管是赋值操作还是参数传递操作--针对原始类型(primitive type),是对堆栈区的原始类型的值进行复制;针对对象,是对储存在堆栈区的,对象的引用中所储存的_对象的值被存储的地址_进行复制。 像上面抠字眼的句子读起来比较费力,我在后面将用两个例子并结合一些示意图来阐述我对这个问题的理解。希望各位朋友帮助纠正错误。 1)、赋值操作: 例子2源码:(Assign.java)
(1),Step 1中,整数i和对象o得到赋值。 示意图3-1-1 从示意图3-1-1中可以看出:整数i存储在堆栈区(Stack);对象o的引用存储在了堆栈区,但是对象o的值却存储在了内存堆中(Heap),对象o的引用存储了对象o的地址。 Step 1在我的机器上的一次输出结果:
http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/io/PrintStream.html#println(java.lang.Object) http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/lang/Object.html#toString() (2),Step 2中,把整数i赋值给了整数j,把对象o赋值给了对象p。 示意图3-1-2 从示意图3-1-2中可以看出:整数i的值复制给了整数j,整数j同样存储在堆栈区;存储在堆栈区的对象o的引用中存储的_对象o的值的地址C_复制给了对象p的引用,对象p的引用同样在堆栈区中。因为对象p的引用_得到了对象o的引用复制过来的_对象o的值的存储地址C,所以对象p的引用_和对象o的引用_都指向了在堆(heap)中的同一个对象,并且,这个对象的地址是地址C。 Step 2在我的机器上的一次输出结果:
示意图3-1-3 从示意图3-1-3中可以看出:整数i的值不变,整数j的值加1变为2,整数在堆栈区中;新生成的对象的值存储在了堆(Heap)中,地址为F。新生成对象的值的地址F_存储在了堆栈区p的引用中,替换了原来存储在其中的地址C。于是,p的引用就指向了新生成的对象,这个新生成的对象的值的地址_是地址F。而整数i和对象o的(包括对象o的引用)没有改变也不曾有任何改变(除了初次赋值)。 Step 3在我的机器上的一次输出结果:
在Java赋值操作中,针对原始类型(primitive type),是对堆栈区的原始类型的值进行复制;针对对象,是对储存在堆栈区的,对象的引用中所储存的_对象的值被存储的地址进行复制。这就是术语:“堆栈区数据复制(Stack Data Copy,简称SDC)”在Java赋值操作中的阐述。 2)、方法中的参数传递操作: 例子2源码:(PassParameter.java)
(1),Step 1中,与上面Assign.java中的Step 1相同,略,下面重复其示意图3-1-1。 示意图3-1-1 Step 1在我的机器上的一次输出结果:
示意图3-2-2 Step 2在我的机器上的一次输出结果:
示意图3-2-3 Step 3和Step 4在我的机器上的一次输出结果:
在Java方法参数传递操作中,针对原始类型(primitive type),是对堆栈区的原始类型的值进行复制;针对对象,是对储存在堆栈区的,对象的引用中所储存的_对象的值被存储的地址进行复制。这就是术语:“堆栈区数据复制(Stack Data Copy,简称SDC)”在Java方法参数传递操作中的阐述。 4,结论 综上所述:在Java中,不管是赋值操作还是方法的参数传递操作--针对原始类型(primitive type),是对堆栈区的原始类型的值进行复制;针对对象,是对储存在堆栈区的,对象的引用中所储存的_对象的值被存储的地址进行复制。 所以,据我的理解,术语:“堆栈区数据复制(Stack Data Copy,简称SDC)”能够有助于理解在Java中进行赋值和传递参数的机制,能够有助于在一定程度上消除“传值”、“传引用”等语义上的多变性的负面影响,可以提出来供大家交流。 5,附注: 由于本人水平有限,上面的一切全是基于实践进行的带有一些推测成分在内的个人心得总结。我也以上面的自创术语去成功解释过一些文章中的有关问题(如下面参考资料中的例程)。谨希望在能为部分Java初学者提供一个理解Java赋值和参数传递的手段的同时,更能得到各位朋友的斧正,以便能够对这个问题形成更加正确和准确的认识。在我提高认识的同时,我会在本文原始出处:用"堆栈区数据复制"理解Java赋值和参数传递机制的心得 (http://java.learndiary.com/disDiaryContentAction.do?goalID=2716)中随时更新此文。再次贴出我的邮件:mdx-xx@tom.com。谢谢。 6,参考资料: 1),Java参数传递方式 (http://www.jiehoo.com/java-pass-parameter.htm) 2),破除java神话之二:参数是传址的 (http://www.javaresearch.org/article/showarticle.jsp?column=544&thread=443) 3),Java 应用程序中的按值传递语义 (http://www.javaresearch.org/article/showarticle.jsp?column=1&thread=706) 4),我对《Java 应用程序中的按值传递语义》的理解 (http://www.javaresearch.org/article/showarticle.jsp?column=1&thread=3156) 5),Thinking in Java, 3rd Edition in Java (http://www.mindviewinc.com/downloads/TIJ-3rd-edition4.0.zip) 全文完 2006年11月22日午首稿 2006年11月24日下午第一次更新 2006年11月28日早晨第二次更新(局部小更新) | ||||||||||||||||||
[align=center]相关资源 [/align] Java参数传递方式 http://www.jiehoo.com/java-pass-parameter.htm 及其文中所提相关文章 Thinking in Java, 3rd Edition in Javahttp://www.mindviewinc.com/downloads/TIJ-3rd-edition4.0.zip |
相关文章推荐
- 用"堆栈区数据复制"理解Java赋值和参数传递?机制的心得
- 用"堆栈区数据复制"理解Java赋值和参数传递?机制的心得
- 转: 用”堆栈区数据复制”理解Java赋值和参数传递机制的心得
- 转: 用”堆栈区数据复制”理解Java赋值和参数传递机制的心得
- 用”堆栈区数据复制”理解Java赋值和参数传递机制的心得
- 理解Java赋值和参数传递机制.docx
- 理解Java赋值和参数传递机制
- 验证参数传递引发的Java编译错误“No enclosing instance of type XXX is accessible" 及匿名内部类
- java程序设计--孙鑫java无难事Lesson5《java常用包、数据类型与引用类型、函数参数传递、克隆机制》
- Java中"Test(Object...args){}"方法声明的理解——J2SE5的“Varargs”机制
- 关于"Java中方法参数的传递方式"的探讨
- 关于"Java中方法参数的传递方式"的探讨
- More Effective C++----(12)理解"抛出一个异常"与"传递一个参数"或"调用一个虚函数"间的差异
- 两段交换代码轻松理解Java参数传递机制
- 深入理解Java中方法的参数传递机制
- WCF实体对象客户端引用时生成多余参数"××Specified",且值类型数据赋值无法传递值时必须付××Specified=true
- 传入的表格格式数据流(TDS)远程过程调用(RPC)协议流不正确。参数 1 (""): 数据类型 0x38 未知。
- 完全掌握java中的"包"机制
- 如果java中一个方法不知道要传递多少参数也不知道传递过来的是什么类型的数据你会怎么做?
- 深入理解java方法调用时的参数传递