Java经典问题:传值与传引用?

转自:http://developer.51cto.com/art/201104/254715.htm

Java到底是传值还是传引用?相信很少有人能完全回答正确。通常的说法是:对于基本数据类型(整型、浮点型、字符型、布尔型等),传值;对于引用类型(对象、数组),传引用。基本类型传值,所有人都不会对此有疑义;问题出在引用类型上。

为引入正题,不妨先看看下面的例子,你能正确给出程序的运行结果嘛?

  1. /**
  2. * @(#)Swap.java
  3. *
  4. *
  5. *  @author
  6. *  @version  1.00 2007/1/5
  7. */
  8. public   class  Swap   {
  9. public  Swap()   {}
  10. public   static   void  main(String[] args)   {
  11. Changer c  =   new  Changer();
  12. String stra  =   " Mighty " ;
  13. String strb  =   " Mouse " ;
  14. c.swap(stra, strb);
  15. System.out.println(stra  +   "   "   +  strb);
  16. String[] strArr  =   new  String[ 2 ] ;
  17. strArr[ 0 ]  =  stra;
  18. strArr[ 1 ]  =  strb;
  19. c.swap(strArr);
  20. System.out.println(strArr[ 0 ]  +    "   "   +  strArr[ 1 ]);
  21. }
  22. static   class  Changer   {
  23. public   < T >   void  swap(T a, T b)   {
  24. T temp  =  a;
  25. a  =  b;
  26. b  =  temp;
  27. }
  28. public   < T >   void  swap(T[] t)   {
  29. if  (t.length  <   2 )   {
  30. System.out.println( " error! " );
  31. return ;
  32. }
  33. T temp  =  t[ 0 ];
  34. t[ 0 ]  =  t[ 1 ];
  35. t[ 1 ]  =  temp;
  36. }
  37. }
  38. }

上面程序的正确运行结果为:

Mighty Mouse

Mouse Mighty

你答对了嘛?

下面我们来分析一下:为什么会出现上面的运行结果?

为分析这个问题,我们必须对程序中的数据在内存中的布局有一定了解。上面main程序中和String相关的变量共有3个,其布局可以用下图所示:

当调用swap(stra, strb)函数时,传递的是引用类型stra、strb的拷贝值,因此函数中任何对参数的改变都不会影响到stra和strb的值;而调用swap(strArr)时,传递的是strArr的拷贝值,程序中对参数的任何改变仍然不会影响到strArr的值,然而swap(T[] t)中改变的并不是strArr的值,而是strArr[0]和strArr[1]的值,也就是引用类型strArr所指向的对象的值,因而strArr[0]和strArr[1]的值发生了变化。

从上面的分析,我们可以得出结论:对于引用类型,其实参数传递时仍然是按值传递的;当然,按引用传递也不是完全没有道理,只是参考对象不是引用类型本身,而是引用类型所指向的对象。

时间: 2024-12-15 18:16:30

Java经典问题:传值与传引用?的相关文章

Java中的传值与传引用

曾经对java中传值还是传引用的问题十分困惑,而且也被问到过许多次,无论是面试,还是平时我们平时的讨论中. 在stackoverflow上面浏览时,无意中发现了跟这个问题有关的论题,于是深入地查看了,感觉获益匪浅,于是结合自己过去的经验,写了这篇博客跟大家分享. 以前我觉得是这样的,java中的基本数据类型和String是传值的,而其它的类类型的数据则是传引用的.不过现在我觉得不是这样的. *****************************************************

Java 中的传值与传引用

Java 函数中的传值和传引用问题一直是个比较"邪门"的问题,其实 Java 函数中的参数都是传递值的,所不同的是对于基本数据类型传递的是参数的一份拷贝,对于类类型传递的是该类参数的引用的拷贝,当在函数体中修改参数值时,无论是基本类型的参数还是引用类型的参数,修改的只是该参数的拷贝,不影响函数实参的值,如果修改的是引用类型的成员值,则该实参引用的成员值是可以改变的,例子如下 class Model { public int i = 0; public String s = "

(转) java 函数形参传值和传引用的区别.

(一)基本数据类型:传值,方法不会改变实参的值. [java] view plain copy public class TestFun { public static void testInt(int i){ i=5; } public static void main(String[] args) { int a=0 ; TestFun.testInt(a); System.out.println("a="+a); } } 程序执行结果:a=0 . (二)对象类型参数:传引用,方法

Java中传值和传引用

今天看了Java中的传值和传引用,对于这一块开始的时候不太能理解,通过查阅其他几篇blog,将自己的理解记录下来: 比较好的几篇blog:http://blog.csdn.net/houpuhope/article/details/7449377; 首先对于传值和传引用需要有一个初步的理解就是,通过传值的方式传进来的参数修改了,对原变量并没有什么影响: 而,通过传引用的方式修改的,原变量值也跟着改变.下面进行详细的解析: 1.对于基本类型Java是按照传值传递的: public class Te

由传值、传引用引发的问题 (Java)

最近在读<算法导论>,在尝试自己实现归并排序时,发现了一个很奇怪的问题. 为了能够专注于问题,下面使用一段重新编写的能够重现问题的代码.可以尝试运行一下. 1 public class Main 2 { 3  public static void main(String[] args) 4  { 5   int[] tmp = {4, 5, 6}; 6   Test.print(tmp); 7   Test.test(tmp); 8   Test.print(tmp); 9  } 10 } 1

C语言结构体,C语言结构体指针,java对象引用,传值,传地址,传引用

C语言结构体,C语言结构体指针,java对象引用,传值,传地址,传引用 传值 把实参的值赋值给行参 那么对行参的修改,不会影响实参的值 传地址 传值的一种特殊方式,只是他传递的是地址,不是普通的如int 那么传地址以后,实参和行参都指向同一个对象 传引用 真正的以地址的方式传递参数 传递以后,行参和实参都是同一个对象,只是他们名字不同而已 对行参的修改将影响实参的值 所谓变量是内存地址的一个抽象名字,在静态编译的程序中,所有变量名都会在编译时转换成内存地址,机器不知道变量名,只知道地址. C 语

Java传值与传引用

在Java中,变量分为以下两类, 1.对于基本类型变量,Java是传值的副本,即时自己的副本变了,自己也不会变化. 2.对于一切对象型变量,Java都是传引用的副本,也就是复制指向地址的指针,它传的引用副本指向自己的地址. eg:你要张三(张三相当于函数)打开仓库,并检查库里面的货物(仓库相当于地址),有必要新建一座仓库(并放入相同的货物)给张三吗? 没有必要,你只需要把钥匙(引用)复制一把给张三即可, 张三会拿复制的钥匙(引用副本,但是有时效性,函数结束,钥匙销毁)打开仓库. 注意:Strin

【转载】Java是传值还是传引用

1. 简单类型是按值传递的 Java 方法的参数是简单类型的时候,是按值传递的 (pass by value).这一点我们可以通过一个简单的例子来说明: /* 例 1 */ /** * @(#) Test.java * @author fancy */ public class Test { public static void test(boolean test) { test = ! test; System.out.println("In test(boolean) : test = &q

Java学习笔记:具体解释传值和传引用

传值和传引用 When you're passing primitives into a method ,you get a distinct copy of the primitive. When you're passing a reference into a method , you get a copy of the reference. 以上引自<Thinging in Java>.总结一下就是无论Java參数的类型是什么.一律传递參数的副本. 在Java中,变量分为以下两类: 对