今天遇到了一个java程序,需要用参数来返回值(虽然最后用另一种方法实现了),在网上看到这样一篇文章,很受启发。 本文章来自于http://hi.baidu.com/xzhilie/blog/item/8bc05c8dbdc86816b21bbae3.html 首先,推荐对Java有一定理解的同仁一本书《Practical Java》。在《Practical Java》中也有一个章节介绍Java中关于传值和传引用的问题,堪称经典。《Practical Java》在Java中,事实上底层工作原理不存在传引用的概念,这也象《Practical Java》中所说的那样,Java中只有传值。这句话理解起来需要费一定的周折。 熟悉C的程序员都用过指针,对指针可谓爱之深恨之切。指针是指向一块内存地址的内存数据(有些拗口),也就是说指针本身是一个占用4字节内存的int(32 位系统内),而这个int值恰恰又是另一块内存的地址。比如"hello"这个字串,存放在@0x0000F000这个地址到@0x0000F005这段内存区域内(包括0x00的结束字节)。而在@0x0000FFF0到@0x0000FFF03这四个字节内存放着一个int,这个int的值是 @0x0000F000。这样就形成了一个指向"hello"字串的指针。 在Java中,很多人说没有指针,事实上,在Java更深层次里,到处都是大师封装好的精美绝伦的指针。为了更容易的讲解Java中关于类和类型的调用,Java中出现了值与引用的说法。浅显的来说,我们可以认为Java中的引用与C中的指针等效(其实差别非常非常大,但是为了说明我们今天的问题,把他们理解为等效是没有任何问题的)。 所谓传引用的说法是为了更好的讲解调用方式。基于上面对指针的理解,我们不难看出,指针其实也是一个int值,所谓传引用,我们是复制了复制了指针的int值进行传递。为了便于理解,我们可以姑且把指针看作一种数据类型,透明化指针的int特性,从而提出传引用的概念。 重申一遍:Java中只有传值。 1所谓传值和传引用 传值和传引用的问题一直是Java里争论的话题。与C++不同的,Java里面没有指针的概念,Java的设计者巧妙的对指针的操作进行了管理。事实上,在懂C++的Java程序员眼中,Java到处都是精美绝伦的指针。 void change(int i){ 很显然的,在mothod1中执行了change(x)后,x的值并不会因为change方法中将输入参数赋值为1而变成1,也就是说在执行change(x)后,x的值z依然是0。这是因为x传递给change(int i)的是值。这就是最简单的传值。 void change(StringBuffer i){ 2非要搞清楚传值还是传引用的问题吗? 搞清楚这自然是有必要的,不然我也不需要写这么多了,不过的确没有到"非要"的地步。
int c=a; 3类型和类 Java 提出的思想,在Java里面任何东西都是类。但是Java里面同时还有简单数据类型int,byte,char,boolean,与这些数据类型相对应的类是Integer,Byte,Character,Boolean,这样做依然不会破坏Java关于任何东西都是类的提法。这里提到数据类型和类似乎和我们要说的传值和传引用的问题无关,但这是我们分辨传值和传引用的基础。 4试图分辨传值还是传引用 为什么是"试图分辨"呢?很简单,传值和传引用的问题无处不在,但是似乎还没有人能正统的给出标准,怎样的就是值拷贝调用,怎样的就是引用调用。面对这个问题,我们更多的应该是来自平时积累对Java的理解。 变量x---->[存放值0] 执行第3行调用change(x)方法的时候,内存中是这样的情形:x把自己值在内存中复制一份,然后变量i指向这个被复制出来的0。 变量x---->[存放值0] 这时候再执行到第7行的时候,变量i的被赋值为7,而这一步的操作已经跟x没有任何关系了。 变量x---->[存放值0] 说到这里应该已经理解为什么change(x)不能改变x的值了吧?因为这个例子是传值的。 变量x---->[存放值"Hello"] 接下来执行第三行change(x),注意,这里就与例1有了本质的不同:调用change(x)时,变量i也指向了x指向的内存空间,而不是指向x的一个拷贝。 变量x \ 于是,第7行对i调用append方法,改变i指向的内存空间的值,x的值也就随之改变了。 变量x \ 为什么x值能改变呢?因为这个例子是传引用的。 变量x---->[存放值"Hello"] 第9行调用change2,将sb指向x指向的内存空间,也就是传入x的引用。 变量x \ 到这里为止还没有什么异样,接下来执行18行,这里就出现了类似传入值拷贝的变化:new 方法并没有改变sb指向内存的内容,而是在内从中开辟了一块新的空间存放串"hi",同时sb指向了这块空间。 变量x---->[存放值"Hello"] 接下来再对sb进行append已经和x没有任何关系了。 a = 2; System.out.println("a=" + a); //例8,打印结果是什么? public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello "); System.out.println("Before change, sb = " + sb); changeData(sb); System.out.println("After changeData(n), sb = " + sb); }
public static void changeData(StringBuffer strBuf) { StringBuffer sb2 = new StringBuffer("Hi "); strBuf = sb2; sb2.append("World!"); } } |
相关文章
- java 多行文本框与自动换行
- Java多线程03——线程安全和线程同步
- android studio导入cocos2dx 3.10的工程问题
- cocos2dx 3.10 Win32和Android引用libcurl库路径问题
- POJ 1321 棋盘问题(DFS & 状压DP)
- Android 类似duplicate entry: android/support/v4/internal/view/SupportSubMenu.class问题解决办法汇总
- IE chrome兼容问题
- SpringCloud服务消费者第一次调用出现超时问题的解决方案
- Java [leetcode 15] 3Sum
- cocos2dx 从win32转到Android的问题