理解Java赋值和参数传递机制
提纲:1、版权声明2、前言3、正文4、结论5、附注6、参考资料=======================================================1、版权声明: 本文作者:little,原始出处:用"堆栈区数据复制"理解Java赋值和参数传递机制的心得 (http://java.learndiary.com/disDiaryContentAction.do?goalID=2716),邮件:mdx-xx@tom.com。如有任何反馈意见请联系作者,作者会在本文原始出处随时更新此文。转载及引用请保留此版权声明,谢谢。2、前言: 关于Java的赋值和参数传递是按值(by value)进行的还是按引用(by reference)进行的,这个问题曾经迷惑了很多人,包括我。而且,我想,这个问题还将继续迷惑一些人,包括那些C++的高手。 在这里,我不准备用“按值(by value)”和“按引用(by value)”这样的术语来阐述这个问题。因为,从字面的理解来看,这样的术语在不同的人头脑里有不同的含义。我试图从Java数据(包括原始类型(primitive type)和对象(ojbect))在内存中的存储这个角度,用一个自创的“术语”来阐述我对这个问题的理解。这个术语就是:“堆栈区数据复制(Stack Data Copy,简称SDC)”。详细一点就是:在Java中,不管是赋值操作还是参数传递操作--针对原始类型(primitive type),是对堆栈区的原始类型的值进行复制;针对对象,是对储存在堆栈区的,对象的引用中所储存的对象的值的地址进行复制。 像上面抠字眼的句子读起来比较费力,我在后面将用两个例子并结合一些示意图来阐述我对这个问题的理解。希望各位朋友帮助纠正错误。3、正文:1)、赋值操作:例子源码:(Assign.java)
- public class Assign{
- public static void main(String[] args){
- int i = 1;
- Object o = new Object();
- System.out.println("i = " + i + " ; o = " + o ); // Step 1 (示意图:3-1-1)
- int j = i;
- Object p = o;
- System.out.println("i = " + i + " ; j = " + j + " ; o = " + o + " ; p = " + p); //Step 2 (示意图:3-1-2)
- j++;
- p = new Object();
- System.out.println("i = " + i + " ; j = " + j + " ; o = " + o + " ; p = " + p); //Step 3 (示意图:3-1-3)
- }
- }
- i = 1 ; o = java.lang.Object@a90653
至于对象o的值输出来怎么会是那个样子,我只能告诉您:在java程序的一次运行过程中,每个Object对象输出这样的值是唯一的,因此可以借此来判断对象的引用指向的对象是否发生了改变。详情请参考Java API 文档(下同,这里给出的是:J2SE 1.5.0 API 中文版):[link]http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/io/PrintStream.html#println(java.lang.Object)[/link][link]http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/lang/Object.html#toString()[/link](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在我的机器上的一次输出结果:
- i = 1 ; j = 1 ; o = java.lang.Object@a90653 ; p = java.lang.Object@a90653
- i = 1 ; j = 2 ; o = java.lang.Object@a90653 ; p = java.lang.Object@de6ced
- public class PassParameter{
- static void showMe(int pi, Object po){
- System.out.println("pi = " + pi + " ; po = " + po); // Step 2 (示意图:3-2-2)
- pi++;
- po = new Object();
- System.out.println("pi = " + pi + " ; po = " + po); // Step 3 (示意图:3-2-3)
- }
- public static void main(String[] args){
- int i = 1;
- Object o = new Object();
- System.out.println("i = " + i + " ; o = " + o); // Step 1 (示意图:3-1-1)
- showMe(i, o);
- System.out.println("i = " + i + " ; o = " + o); // Step 4 (示意图:3-2-3)
- }
- }
- i = 1 ; o = java.lang.Object@a90653
(2),Step 2中,与上面Assign.java中的Step 2类似,只是Assign.java中的整数j和对象p变成了这里的方法showMe()中的参数:整数pi和对象po。并且,由于这里是参数传递,把Assign.java示意图3-1-2中的“=”替换成PassParameter.java示意图3-2-2中的“<--”,以此表示是参数传递。据我的理解,它们是一回事。示意图3-2-2Step 2在我的机器上的一次输出结果:
- pi = 1 ; po = java.lang.Object@a90653
- pi = 2 ; po = java.lang.Object@de6ced
- i = 1 ; o = java.lang.Object@a90653
以上是 理解Java赋值和参数传递机制 的全部内容, 来源链接: utcz.com/p/204696.html