fuliang2008
发贴: 4
积分: 0
|
于 2005-08-01 13:05
有关java与c++引用的深度探讨(让你走出经典书籍中的误区): (Author by jlu fuliang) 在java和C++中都采用了引用这个概念,但是二者的行为并不一样。java的引用其实更象 c++中的指针,而非c++中的引用。在许多书上都没有见到关于java中reference行为的更 详细的探讨,本文便从二者的区别谈起,并引出java在object作为函数参数的时候,其 传递行为究竟是by value还是by reference。 一.先看java中的引用: class Person { private String name; public Person(String name) { this.name=name; } public String getName() { return name; } } 现产生两个对象 : Person p1=new Person("Zhangsan"); Person p2=new Person("Lisi"); 引用Person p=p1,p1=p2; 测试结果p.getName(): Zhangsan; p1.getName():Lisi; P2.getName :Lisi; 而在c++的引用中 其结果应该都是Lisi即p2的name(p1的改变会影响p); 上述结果显示:在java中referece其行为就是c++中的指针, 但是java的referece是一种安全的指针,不仅受到编译器的保护,还受到执行系统的保护。但java没有 “指针”运算。 二、反驳经典java书籍中的论点: 既然java中的referece的行为更象指针。那么下面来看看其作为参数传的的时候行为究竟如何(by value or by referece): 在一些经典的java书上(《Core java》和《Thinking in java》堪称是最经典的两部了吧),书上都明确指出All by Value. 即:不管是基本类型还是object都是值传递,并举了足以“让高手信服的例子”,笔者认为其论据“严重不足”: 原文如下(<<core java>>中的例子): public static void swap(Employee x, Employee y) // doesn't work { Employee temp = x; x = y; y = temp; } If the Java programming language used call by reference for objects, this method would work: Employee a = new Employee("Alice", . . .); Employee b = new Employee("Bob", . . .); swap(a, b); // does a now refer to Bob, b to Alice? However, the method does not actually change the object references that are stored in the variables a and b. The x and y parameters of the swap method are initialized with copies of these references. The method then proceeds to swap these copies. // x refers to Alice, y to Bob Employee temp = x; x = y; y = temp; // now x refers to Bob, y to Alice 上述例子的漏洞在于: 假设传递方式为by referece,看一下swap函数的行为: 交换的只是x,y的两个引用(行为更象指针)值即(其中--->表示引用的指向) x---> 名字为Alice的对象 <---a y---> 名字为Bob的对象<---b 现在x,y的指向发生交换,和a,b的指向没有丝毫的关系 当然a,b所指的对象也不会交换: "If the Java programming language used call by reference for objects, this method would work:" 这句话显然是不正确的。 对c++比较熟悉的可将上述的函数转换成: public static void swap(Employee *x, Employee *y) // doesn't work { Employee *temp = x; x = y; y = temp; } Employee *a = new Employee("Alice", . . .); Employee *b = new Employee("Bob", . . .); swap(a, b); 其结果:a,b不会发生改变(犯糊涂可以上机测试一下) 三、探索究竟: 还是一这个程序为例: public static void swap(Employee x, Employee y) // doesn't work { System.out.println("x "+x+",y"+y);会打印出x,y引用的对象,含有其地址 Employee temp = x; x = y; y = temp; } Employee a = new Employee("Alice", . . .); Employee b = new Employee("Bob", . . .); System.out.println("a "+a+",b "+b); 会打印出a,b引用的对象,含有其地址 结果会显示a和x,b和y中对象地址值一样 可见在传递参数的时候并没有产生副本,(这与by referece的传递行为一样) 而在值传递的时候却是要产生副本的。 综上可见java在传递参数的时候是采用: 基本类型采用by value,object采用by referece; 四、上述探讨只是个人认为,由于水平有限,如果有误,还望高手多多指教。
|