java传值引用.doc

上传人:公**** 文档编号:542983419 上传时间:2024-02-27 格式:DOC 页数:8 大小:36.50KB
返回 下载 相关 举报
java传值引用.doc_第1页
第1页 / 共8页
java传值引用.doc_第2页
第2页 / 共8页
java传值引用.doc_第3页
第3页 / 共8页
java传值引用.doc_第4页
第4页 / 共8页
java传值引用.doc_第5页
第5页 / 共8页
点击查看更多>>
资源描述

《java传值引用.doc》由会员分享,可在线阅读,更多相关《java传值引用.doc(8页珍藏版)》请在金锄头文库上搜索。

1、浅谈在Java语言中究竟是传值还是传引用 来源: 网络转载 时间:2009-6-15 首先,推荐对Java有一定理解的同仁一本书Practical Java。在Practical Java中也有一个章节介绍Java中关于传值和传引用的问题,堪称经典。Practical Java在Java中,事实上底层工作原理不存在传引用的概念,这也象Practical Java中所说的那样,Java中只有传值。这句话理解起来需要费一定的周折。熟悉C的程序员都用过指针,对指针可谓爱之深恨之切。指针是指向一块内存地址的内存数据(有些拗口),也就是说指针本身是一个占用4字节内存的int(32 位系统内),而这个in

2、t值恰恰又是另一块内存的地址。比如hello这个字串,存放在0x0000F000这个地址到0x0000F005这段内存区域内(包括0x00的结束字节)。而在0x0000FFF0到0x0000FFF03这四个字节内存放着一个int,这个int的值是 0x0000F000。这样就形成了一个指向hello字串的指针。在Java中,很多人说没有指针,事实上,在Java更深层次里,到处都是大师封装好的精美绝伦的指针。为了更容易的讲解Java中关于类和类型的调用,Java中出现了值与引用的说法。浅显的来说,我们可以认为 Java中的引用与C中的指针等效(其实差别非常非常大,但是为了说明我们今天的问题,把他

3、们理解为等效是没有任何问题的)。所谓传引用的说法是为了更好的讲解调用方式。基于上面对指针的理解,我们不难看出,指针其实也是一个int值,所谓传引用,我们是复制了复制了指针的int值进行传递。为了便于理解,我们可以姑且把指针看作一种数据类型,透明化指针的int特性,从而提出传引用的概念。重申一遍:Java中只有传值。1.所谓传值和传引用传值和传引用的问题一直是Java里争论的话题。与C+不同的,Java里面没有指针的概念,Java的设计者巧妙的对指针的操作进行了管理。事实上,在懂C+的Java程序员眼中,Java到处都是精美绝伦的指针。下面举个简单的例子,说明什么是传值,什么是传引用。/例1vo

4、id method1()int x=0;this.change(x);System.out.println(x);void int change(int i) i=1;很显然的,在mothod1中执行了change(x)后,x的值并不会因为change方法中将输入参数赋值为1而变成1,也就是说在执行change(x)后,x的值z依然是0。这是因为x传递给change(int i)的是值。这就是最简单的传值。同样的,进行一点简单的变化。/例2void method1()StringBuffer x=new StringBuffer(Hello);this.change(x);System.out

5、.println(x);void int change(StringBuffer i) i.append( world!);看起来没什么变化,但是这次mothed1中执行了change (x)后,x的值不再是Hello了,而是变成了Hello world!。这是因为x传递给change(i)的是x的引用。这是最经典的传引用。似乎有些奇怪了,两段程序没有特别的不同,可是为什么一个传的是值而另一个传的是引用呢?.2.非要搞清楚传值还是传引用的问题吗?搞清楚这自然是有必要的,不然我也不需要写这么多了,不过的确没有到非要的地步。首先,如果我们不太关心什么是传值什么是传引用,我们一样能写出漂亮的代码,但

6、是这些代码在运行过程中可能会存在着极大的隐患。全局变量是让大家深恶痛绝(又难以割舍)的东西,原因就是使用全局变量要特别注意数据的保护。如果在多线程的程序里使用全局变量简直就等于跟自己过不去。不了解传值和传引用的问题,跟使用全局变量不考虑数据保护的罪过是不相上下下的,甚至有时候比它还要糟。你会莫名其妙,为什么我的返回参数没有起作用,为什么我传进去的参数变成了这样.?一个例子:/例3void mothed1() int x=0; int y=1; switchValue(x,y); System.out.println(x=+x); System.out.println(y=+y);void sw

7、itchValue(int a,int b) int c=a; a=b; b=c;上面是一个交换a,b值的函数,看起来似乎蛮正确的,但是这个函数永远也不会完成你想要的工作。还有一个例子:/例4StringBuffer a=new StringBuffer(I am a );StringBuffer b=a;a.append(after append);a=b;System.out.println(a=+a);在编程过程中,经常会遇到这种情况,一个变量的值要被临时改变一下,等用完之后再恢复到开始的值。就好像上面的例子,a为了保持它的值,使用b=a做赋值,之后a被改变,再之后a把暂存在b里面的值取

8、回来。这是我们一厢情愿的想法,而事实上,这段代码执行后,你会发现a的值已经改变了。以上是两个最简单的例子,真正的程序开发过程中,比这要复杂的情况每天都会遇到。3.类型和类Java 提出的思想,在Java里面任何东西都是类。但是Java里面同时还有简单数据类型:int,byte,char,boolean,与这些数据类型相对应的类是Integer,Byte,Character,Boolean,这样做依然不会破坏Java关于任何东西都是类的提法。这里提到数据类型和类似乎和我们要说的传值和传引用的问题无关,但这是我们分辨传值和传引用的基础。4试图分辨传值还是传引用为什么是试图分辨呢?很简单,传值和传引

9、用的问题无处不在,但是似乎还没有人能正统的给出标准,怎样的就是值拷贝调用,怎样的就是引用调用。面对这个问题,我们更多的应该是来自平时积累对Java的理解。回过头来,我们分析一下上面的几个例子:先看例1,即使你不明白为什么,但是你应该知道这样做肯定不会改变x的值。为了方便说明,我们给例子都加上行号。/例11 void method1()2 int x=0;3 this.change(x);4 56 void int change(int i)7 i=7;8让我们从内存的存储方式看一下x和I之间到底是什么关系。在执行到第2行的时候,变量x指向一个存放着int 0的内存地址。变量x-存放值0执行第3

10、行调用change(x)方法的时候,内存中是这样的情形:x把自己值在内存中复制一份,然后变量i指向这个被复制出来的0。变量x-存放值0进行了一次值复制变量x-存放值0这时候再执行到第7行的时候,变量i的被赋值为7,而这一步的操作已经跟x没有任何关系了。变量x-存放值0变量x-存放值7说到这里应该已经理解为什么change(x)不能改变x的值了吧?因为这个例子是传值的。那么,试着分析一下为什么例三中的switchValue()方法不能完成变量值交换的工作?再看例2。/例21void method1()2 StringBuffer x=new StringBuffer(Hello);3 this.

11、change(x);456void int change(StringBuffer i)7 i.append( world!);8例2似乎和例1从代码上看不出什么差别,但是执行结果却是change(x)能改变x的值。依然才从内存的存储角度来看看例2的蹊跷在哪里。在执行到第2行时候,同例1一样,x指向一个存放Hello的内存空间。变量x-存放值Hello接下来执行第三行change(x),注意,这里就与例1有了本质的不同:调用change(x)时,变量i也指向了x指向的内存空间,而不是指向x的一个拷贝。变量x -存放值Hello变量x /于是,第7行对i调用append方法,改变i指向的内存空间

12、的值,x的值也就随之改变了。变量x -追加为Hello World!变量x /为什么x值能改变呢?因为这个例子是传引用的。这几个例子是明白了,可是很多人会开始有另一个疑问了:这样看来,到底什么时候是传的值什么时候是传得引用呢?于是,我们前面讲到的类型和类在这里就派上了用场:对于参数传递,如果是简单数据类型,那么它传递的是值拷贝,对于类的实例它传递的是类的引用。需要注意的是,这条规则只适用于参数传递。为什么这么说呢?我们看看这样一个例子:/例5String str=abcdefghijk;str.replaceAll(b,B);这两句执行后,str的内容依然是abcdefghijk,但是我们明明

13、是对str操作的,为什么是这样的呢?因为str的值究竟会不会被改变完全取决于replaceAll这个方法是怎么实现的。类似的,有这样一个例子:/例61 void method1() 2 StringBuffer x = new StringBuffer(Hello);3 change1(x);4 System.out.println(x);5 67 void method2() 8 StringBuffer x = new StringBuffer(Hello);9 change2(x);10 System.out.println(x);11 1213 void change1(StringB

14、uffer sb) 14 sb.append( world!);15 1617 void change2(StringBuffer sb) 18 sb = new StringBuffer(hi);19 sb.append( world!);20 调用method1(),屏幕打印结果为:Hello world!调用method2(),我们认为结果应该是hi world,因为sb传进来的是引用。可是实际执行的结果是Hello!难道change2()又变成传值了?!其实change1()和change2()的确都是通过参数传入引用,但是在方法内部因为处理方法的不同而使结果大相径庭。我们还是从内存的角度分析:执行method1()和change1()不用再多说了,上面的例子已经讲解过,这里我们分析一下method2()和change2()。程序执行到第8行,x指向一个存放着Hello的内存空间。变量x-存放值Hello第9行调用change2,将sb指向x指向的内存空间,也就是传

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 社会民生

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号