浏览 3486 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-02-26
最后修改:2009-03-03
public class Point{ private int x; private int y; public Point(int x,int y){ this.x = x; this.y = y; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } } public class ParameterTest { public void changeInt(int a){ a = 3; } public void changePoint(Point point){ point.setX(5); point.setY(6); } public void changeString(String str){ str = "abc"; System.out.println(str); } public static void main(String[] args){ int a = 1;//语句(1) ParameterTest pt = new ParameterTest();//语句(2) pt.changeInt(a);//语句(3) System.out.println(a);//语句(4) Point point = new Point(1,2);//语句(5) pt.changePoint(point);//语句(6) System.out.println(point.getX());//语句(7) System.out.println(point.getY());//语句(8) String str = "xyz";//语句(9) pt.changeString(str);//语句(10) System.out.println(str);//语句(11) } } 问题1:当执行完语句(4)后,打印的结果是什么?为什么? 解答:当执行完语句(4)后,打印的结果是1。分析:首先调用定义 int a = 1;然后调用对象的changeInt(int a)方法,流程转到changeInt方法里面去,把a的值赋给了方法changeInt的形式参数,changeInt方法里面参数a的值为1,然后执行性方法体里的语句a = 3,即是将changeInt方法里面参数a的值由1改为3;注意:这个时候对方法changeInt方法里面参数a的值改变并没有影响到main方法里面的a的值,为什么?对于原生数据类型来说,它仅仅是把 main方法里面的a的值传过去,传值完后,两者之间没有任何的关系,你在changeInt方法里面对参数a的改变,对外面main方法的a没有任何的影响。因为我只是把值拷贝一份给你,拷贝完以后,你是你的我是我的,两者之间没有任何关系。因此,当执行完语句(4)后,打印结果是4。 总结:对八种原生数据类型来说,它们传递的时候传递的是它们的值(value),是值的拷贝,拷贝过去过后,你是你,我是我,两者之间无任何关系。所以,方法里面对拷贝过来的值的改变,对被拷贝的原生数据类型没有任何的影响。 问题2:当执行完语句(7)(8)后,打印的结果是什么?为什么? 解答:当执行完语句(7)(8)后,打印的结果分别是5,6。分析:语句(5)Point point = new Point(1,2),首先生成一个横坐标是1,纵坐标是2的Point对象,因为有关键字new...,point是指向刚生成的这个对象的引用,即是刚生成的对象的内存地址,接着执行语句(6),调用changePoint方法,它会把引用point传过去赋值给changePoint(Point point)里面的point.注意:传的是引用,即是对象的内存地址,接着把对象的x改为5,y改为6,这时对象的横纵坐标发生了改变,分别变为5和6。也就是说,在changePoint方法里面,对point所指向的对象的x和y的改变会反应到你外面生成的这个对象,也就是1被改成了5,2被改成了6。这个对象为什么会改变?这就涉及到 java对引用类型的传递方式上,首先语句(5)表示在内存的堆里面生成了一个Point类型的对象,point这个引用它指向堆里面生成的Point类型的对象,这个对象里x坐标是1,y坐标是2。接着去调用changePoint方法,在调用这个方法的时候,它会把point这个引用传给changePoint方法里面的point参数。在java里面,引用在java里面是对象在内存堆里面的地址,它是把对象的地址传递到了changePoint方法里面去了。地址本身也是一个int类型的值,它把地址通过参数的形式传递过去。举例:比如说new Point(1,2)这个对象在内存堆中的地址是1234,那么调用changePoint方法,它传给changePoint(Point point)里面的point的地址也是1234,changePoint方法外面的引用指向了堆里面生成的Point类型的对象,那么对changePoint方法里面的参数引用也指向同一个堆里面生成的Point类型的对象,java里面只要有两个引用它们的地址是一样的必然指向同一个对象。所以说当changePoint方法调用的时候,方法里面的引用和方法外面的引用它们指向的是同一个对象,究其原因它们是内存地址的传递,两个引用的内存地址是一样的必然指向同一个对象。通过执行changePoint方法里面的语句,把这个引用指向的对象的x改为5,y改为6。然后方法结束,结束之后,我打印changePoint方法外面这个引用它所指向对象的x坐标和y坐标,因为这两个引用指向的是同一个对象,所以结果是5和6。 问题3:当执行完语句(11)后,打印的结果是什么?为什么? 解答:当执行完语句(11)后,打印的结果是xyz。分析:语句(9) String str = "xyz";表示str这个引用指向常量"xyz"(在String Pool里面),当执行语句(10)的changeString(String str)方法时,将全局的str引用传递给changeString方法里面的str,这时会导致全局的str引用和changeString方法里面的引用会指向同一个对象"xyz",所以当完成参数传递还没有执行方法里面的语句体的时候,它们的引用是指向同一个对象"xyz"的,接着执行方法体里面的语句,这时会在String Pool里面生成一个"abc"的对象,同时将方法体里面的str指向String Pool里面的"abc"对象。一个引用在某一时刻始终只能指向一个对象,changString方法外面的str始终是指向"xyz"对象的。所以输出的时候始终是"xyz"。 总结: 在java里面,对方法的参数传递,不管是原生数据类型还是引用类型,一律是传值:pass by value。对原生数据类型来说,传递的值就是它被赋予的那个值,比如说 int a = 3 就把3这个值传到方法里面去;引用类型来说,引用本身是一个地址,是一个int类型的内存地址值,所以说它把这个值传递到方法里面去传递的也是值。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-02-27
问题2:当执行完语句(7)(8)后,打印的结果是什么?为什么?
还是有点乱! |
|
返回顶楼 | |
发表时间:2009-02-28
简单的说就是后面总结的一句,PASS BY VALUE。通过值传递。
你一定觉得是传对象时就成了传引用了?对象没有值,所以传引用。(不知道说得对不对。) 传对象是传它 “引用的值”,也就是上面的point,引用的值就是内存地址了,LZ说了也是一个INT值。而不是对象的状态,point(1,2),在changPoint里改变值时是改变了”point这个引用“指向的对象的值。这里的point引用,是从外面传进来的,所以这里变了值,外面也变了。 |
|
返回顶楼 | |
发表时间:2009-02-28
上面说“ 你一定觉得是传对象时就成了传引用了?对象没有值,所以传引用。(不知道说得对不对。) ”这个说法不对,java里面没有传引用这一说,java里面一律是PASS BY VALUE,在C++里面才有传引用,这点要注意java和C++的传值区别,不要搞混淆了! 在java中你只要记住一句话PASS BY VALUE,一切参数传递都适用! |
|
返回顶楼 | |
发表时间:2010-01-12
楼主的文章都总结的非常好!非常感谢。
转载几篇到我空间中;当然了,出处是一定会标名的,呵呵。。。 提一个小意见:问题一的解答里,出现前后矛盾了!应该是手误吧。。。 |
|
返回顶楼 | |