文选流氓 发表于 2003-2-6 15:49

1-1-4-1-3 Java中的参数传递之个人见解[引用和传值]


发信人: virtualmfc (苦苦追求永远追求不到的东西), 信区: Java      
标题: Java中的参数传递之个人见解[引用和传值]
发信站: BBS 水木清华站 (Thu Aug 22 11:27:05 2002), 站内信件

大家对C++中的引用和传值函数调用应该不陌生。然而,初次接触Java后,被这个问题着实
迷惑了一阵子。在看了IBM的Java园地中相关的文章后,有些想法,大胆讲出来,希望能听
到不同的声音。
在C++中,有三种参数传递方法,一种是传值、一种是传址、一种是引用。下面分别列出这
三种的情形:
//传值调用swap
void swap(int a,int b)
{
      int tmp = a;
      a = b;
      b = a;
}
void swap2(int * a,int *b)
{
      int tmp = *a;
      *a = *b;
      *b = tmp;
}
void swap3(int &a,int &b)
{
      int tmp = a;
      a = b;
      b = tmp;
}
int main(int argc,char **argv)
{
      int a = 3;
      int b = 5;
      swap(a,b);
      swap2(&a,&b);
      swap3(a,b);
}
内部机制用图形表示比较直观一点:(变量地址是假设的,依情况不同而变化)
/*****************main中**********************\
变量名       a                                              b
值             3                                              5
内存地址    0x7200                                 0x71FE
****************函数swap中********************
变量名       a                                              b
值             3                                              5
内存地址    0x9200                                 0x91FE
*****************执行完成后**********************
变量名       a                                              b
值             5                                              3
内存地址    0x9200                                 0x91FE
\********************************************/
可以看出,由于C++中的传值调用问题,所以虽然swap(int,int)函数中的局部变量a,b的值
改变了,但因为此a,b与main中的
彼a,b是内存中的不同存储单元,所以对main中的变量毫无影响。swap(int,int)不能完成
交换的任务。
/*****************main中**********************\
变量名       a                                              b
值             3                                              5
内存地址    0x7200                                 0x71FE
****************函数swap2中********************
变量名       a                                              b
值             0x7200                                 0x71FE
内存地址    0x9200                                 0x91FE
*****************执行完成后**********************
变量名       a                                              b
值             5                                              3
内存地址    0x9200                                 0x91FE
\********************************************/
同样分析,由于C++传递参数时始终是传值调用(下面我们将看到,引用也不例外,只是稍
微有点特殊 ),所以,main()函
数中的a和b分别布局在内存中的0x7200和0x71FE处,调用swap2(int *,int *)后,函数sw
ap2(int *,int *)中的局部指针变量a,b的位址是0x9200和0x91FE,然而,其值是0x7200和
0x71FE,分别指向main函数中的a,b。
所以,经过调用后,main函数中的a,b会交换值。函数swap2(int *,int *)可以正常工作。

下面要特别注意,这正是Java和C++不同的地方,也是特别容易混淆的地方。
/*****************main中**********************\
变量名       a                                              b
值             3                                              5
内存地址    0x7200                                 0x71FE
****************函数swap3中********************
变量名       a                                              b
值             0x7200                                 0x71FE
内存地址    0x9200                                 0x91FE
*****************执行完成后**********************
变量名       a                                              b
值             5                                              3
内存地址    0x9200                                 0x91FE
\********************************************/
引用的机制在C++中我不是很清楚,但有一点,它的工作机制非常象指针,只是不用进行解
引用操作。而且,引用不能赋值,只能进行初始化。(请注意这句话)。所以,我们常常
叫它别名。
void swap3(int &a,int &b)
{
      int tmp = a; // a是主函数main中的局部变量a的引用,或者说,指向main中的植勘淞
a
      a = b;//b是主函数main中的局部变量b的引用,或者说,指向main中的局部变縝
      b = tmp;//以上由于引用的特性,所以a=b时,不是说a引用b,而是b的值赋给a,b=tmp是
同样的。
      
      //由于这里的a,b和main中的a,b是同一个东西,所以也完成了交换值的任务。
}
而java中除了此引用外,同样也是传值,但与其说Java中的引用叫引用,不如称之为指针
。使用下面的java示例可以说明问题
class Swap
{
public static void main(String args[])
{
    Integer a, b;
    a = new Integer(10);
    b = new Integer(50);
    System.out.println("before swap...");
    System.out.println("a is " + a);
    System.out.println("b is " + b);
    swap(a, b);
    System.out.println("after swap...");
    System.out.println("a is " + a);
    System.out.println("b is " + b);
}
public static void swap(Integer a, Integer b)
{
    Integer temp = a; //a,b是main方法中的a,b的指针
    a = b;//a指向b
    b = temp;//b指向a
   
    //因为只有swap方法中的局部参数变量a,b的指针指向变化,所以对main方法中的数值
毫无影响。
}
}
再举一个更能说明问题的例子,来说明java中的对象引用不同C++一样,只能初始化,而且
可以任意指向的问题(所以我认为更适合称之为“自解引用指针”)。
import java.awt.Point;
public class Assign {
                int a = 1;
                int b = 2;
                Point x = new Point(0,0);
                Point y = new Point(1,1);      
               
      public static void main(String[] args) {
                System.out.println("a is " + a);
                System.out.println("b is " + b);
                System.out.println("x is " + x);
                System.out.println("y is " + y);
               
                System.out.println("Performing assignment and" + "setLocation...");
               
                a = b; // a == 2
                a ++; // a == 3
                x = y; // x指向y
                x.setLocation(5,5); //x指向的point的值为,因为x指向y,所以Point y的值也为

                //原来x指向的point(0,0)已经丢失了,象C++中的内存泄露一样,不过挥玫P模琂ava
的垃圾收
                //集器会帮忙料理的,不用担心。
               
                System.out.println("a is " + a);
                System.out.println("b is " + b);
                System.out.println("x is " + x);// x ==
                System.out.println("y is " + y); // y ==
      }
}
好了,现在大家应该清楚Java中的参数传递和所谓的“引用传递”了吧。写了这么多,还
是这么一句话,我个人认为,Java中称对象传递的是引用并不恰当。改成“自解引用指针
”对C/C++程序员可能更好理解。大家认为呢?

页: [1]
查看完整版本: 1-1-4-1-3 Java中的参数传递之个人见解[引用和传值]