关于Java交换两个对象的问题

来源:互联网 发布:匿名内部类java构造器 编辑:程序博客网 时间:2024/04/16 19:53

关于Java交换两个对象的问题

 

        对于C++比较熟悉的童鞋,应该知道在函数传参时,有传值、传地址(指针)和传引用这3种。众所周知,Java中没有指针,所以只有传值和传引用两种。

        很容易理解,Java的基本类型,例如int、float等,都是传值。而对象采用传引用,因为对象如果采用传值的话,要复制一份对象中的所有数据,这个开销太大了,实现起来也很麻烦(学过C++的,就知道要实现复制构造函数、重载赋值运算符等,总之很麻烦)。

        近日,浏览了网上关于传引用还是传值的问题,参见后面的参考资料。于是,记下自己的理解。以下面的Java代码为例。

[java] view plaincopy
  1. public class Test {  
  2.       
  3.     public String str;  
  4.       
  5.     public Test(String str) {  
  6.         this.str = str;  
  7.     }  
  8.   
  9.     public static void swapString(String a, String b) {  
  10.         String t = a;  
  11.         a = b;  
  12.         b = t;  
  13.           
  14.         System.out.println("In swapString: " + a + " " + b);  
  15.     }  
  16.       
  17.     public static void swapObject(Test t1, Test t2) {  
  18.         Test temp = t2;  
  19.         t2 = t1;  
  20.         t1 = temp;  
  21.           
  22.         System.out.println("In swapObject: " + t1.str + " " + t2.str);  
  23.     }  
  24.       
  25.     public static void changeObject(Test t) {  
  26.         t.str = "No";  
  27.     }  
  28.       
  29.     public static Test modifyObject(Test t) {  
  30.         t.str = "Bad";  
  31.           
  32.         return t;  
  33.     }  
  34.       
  35.     public static void main(String[] args) {  
  36.           
  37.         // Try to swap two strings  
  38.         String str1 = "Hello";  
  39.         String str2 = "World";  
  40.         swapString(str1, str2);  
  41.         System.out.println("After: " + str1 + " " + str2);  
  42.           
  43.         // Try to swap two objects  
  44.         Test test1 = new Test("Hello");  
  45.         Test test2 = new Test("World");  
  46.         swapObject(test1, test2);  
  47.         System.out.println("After: " + test1.str + " " + test2.str);  
  48.           
  49.         // Try to change an object's field  
  50.         Test test3 = new Test("Yes");  
  51.         changeObject(test3);  
  52.         System.out.println(test3.str);  
  53.           
  54.         // Try to modify an object's field  
  55.         Test test4 = new Test("Good");  
  56.         Test test5 = modifyObject(test4);  
  57.         System.out.println(test4.str);  
  58.         System.out.println(test5.str);  
  59.     }  
  60. }  

输出结果:

[plain] view plaincopy
  1. In swapString: World Hello  
  2. After: Hello World  
  3. In swapObject: World Hello  
  4. After: Hello World  
  5. No  
  6. Bad  
  7. Bad  

        很明显,两个swap方法(swapString和swapObject)都没有成功,而changeObject和modifyObject方法都改变了对象中的字段(field)。但是,注意在swapString和swapObject方法,交换是成功的。这说明通过引用可以修改对象中的字段,但是方法中可以交换两个形参的引用,但是实际上改变不了实参的引用。

        借这个例子,我想说的是,“Java中对象是按引用传的,但是传的是引用的值”。这句话不好理解,我用下面的C代码解释。

[cpp] view plaincopy
  1. #include <stdio.h>  
  2.   
  3. void swap(int* a, int* b)  
  4. {  
  5.     int *t = b;  
  6.     b = a;  
  7.     a = t;  
  8.     printf("In swap: %d %d\n", *a, *b);  
  9. }  
  10.   
  11. void main(void)  
  12. {  
  13.     int a = 1;  
  14.     int b = 2;  
  15.     swap(&a, &b);  
  16.     printf("%d %d\n", a, b);  
  17. }  

输出结果:

[plain] view plaincopy
  1. In swap: 2 1  
  2. 1 2  

        这个C代码的swap和上面Java代码的swap,实质上是一样的,交换的都是指针的值,而不是指针指向对象!(Java封装了指针,只是看不了而已)。

        以上是个人理解,仅供参考。

0 0