Topic: 有关java与c++引用的深度探讨(让你走出经典书籍中的误区):

  Print this page

1.有关java与c++引用的深度探讨(让你走出经典书籍中的误区): Copy to clipboard
Posted by: fuliang2008
Posted on: 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;
四、上述探讨只是个人认为,由于水平有限,如果有误,还望高手多多指教。

2.Re:有关java与c++引用的深度探讨(让你走出经典书籍中的误区): [Re: fuliang2008] Copy to clipboard
Posted by: ranchgirl
Posted on: 2005-08-02 10:01

Please don't copy your wrong comments (误人子弟文章) everywhere to confuse beginners.
Thanks!

Probably, you would not think Sun Microsystem and Dr. James Gosling are also 严重不足, should learn Java from you.

fuliang wrote:
二、反驳经典java书籍中的论点:
既然java中的referece的行为更象指针。那么下面来看看其作为参数传的的时候行为究竟如何(by value or by referece):
在一些经典的java书上(《Core java》和《Thinking in java》堪称是最经典的两部了吧),书上都明确指出All by Value.
即:不管是基本类型还是object都是值传递,并举了足以“让高手信服的例子”,笔者认为其论据“严重不足”:


Q. Can you provide some authoritative quotation to support the saying "In Java, everything is pass-by-value"?
A:
From The Java Programming Language, by James Gosling et al. 3rd edition (pg. 56):


Some people will say incorrectly that objects are passed "by reference." In programming language design, the term pass by reference properly means that when an argument is passed to a function, the invoked function gets a reference to the original value, not a copy of its value. If the function modifies its parameter, the value in the calling code will be changed because the argument and parameter use the same slot in memory. The Java programming language does not pass objects by reference; it passes object references by value. Because two copies of the same reference refer to the same actual object, changes made through one reference variable are visible through the other. There is exactly one parameter passing mode -- pass by value -- and that helps keep things simple.


From Sun's The Java Tutorial
http://java.sun.com/docs/books/tutorial/java/javaOO/arguments.html

Pass by Value
In Java methods, arguments are passed by value.

When invoked, the method receives the value of the variable passed in. When the argument is of primitive type, pass-by-value means that the method cannot change its value. When the argument is of reference type, pass-by-value means that the method cannot change the object reference, but can invoke the object's methods and modify the accessible variables within the object.

This is often the source of confusion--a rogrammer writes a method that attempts to modify the value of one its arguments and the method doesn't work as expected. Let's look at such method and then investigate how to change it so that it does what the programmer originally intended.


http://java.sun.com/developer/Quizzes/techtips1/
Java Quiz question from Sun
In Java programming, all method parameters are passed by value.
Answer: true .


In Java, everything is pass-by-value, unless you think Dr. James Gosling forgot how he invented Java, AND Sun does not know how Java works.If we all agree those are not the cases. Then the question should change to that how to understand the fact "In Java, everything is pass-by-value".If you go up-and-down a little, you will find a lot of help here.

Copied from
http://bobcat.webappcabaret.net/javachina/faq/07.htm#pas_Q5

All links in the above are valid.

3.Re:有关java与c++引用的深度探讨(让你走出经典书籍中的误区): [Re: fuliang2008] Copy to clipboard
Posted by: ranchgirl
Posted on: 2005-08-02 10:11

To everyone else, you can read some more from this link:

http://bobcat.webappcabaret.net/javachina/faq/07.htm#pass_val

4.Re:有关java与c++引用的深度探讨(让你走出经典书籍中的误区): [Re: fuliang2008] Copy to clipboard
Posted by: fuliang2008
Posted on: 2005-08-03 20:51

先对大家说声对不起,我所说by value的意思可能和各位名家以及sun的意思
有所不同,也可能受c++影响太重。现向大家澄清一下事实(发贴前我也没有意识
到这个问题,我在看《Thinking in java》第二版 我可能误会作者,作者在标题上写的是Pass by value,但后面也没有说自己的观点。)(讽刺的是今天我要引用《Thinking in java》第一版 来说明我对by value的理解和各位名家以及sun的理解)
1) Java按值传递任何东西。若将基本数据类型传递进入一个方法,会明确得到基本数据类型的一个副本。但若将一个句柄传递进入方法,得到的是句柄的副本。所以人们认为“一切”都按值传递。当然,这种说法也有一个前提:句柄肯定也会被传递。但Java的设计方案似乎有些超前,允许我们忽略(大多数时候)自己处理的是一个句柄。也就是说,它允许我们将句柄假想成“对象”,(所以说object也是传值)因为在发出方法调用时,系统会自动照管两者间的差异。
(2) Java主要按值传递(无自变量),但对象却是按引用传递的。得到这个结论的前提是句柄只是对象的一个“别名”,所以不考虑传递句柄的问题,而是直接指出“我准备传递对象”。由于将其传递进入一个方法时没有获得对象的一个本地副本,所以对象显然不是按值传递的。Sun公司似乎在某种程度上支持这一见解,因为它“保留但未实现”的关键字之一便是byvalue(按值)。但没人知道那个关键字什么时候可以发挥作用。
我所说的by value正式第(2)中理解 ,而sun则是第一种理解。

5.Re:有关java与c++引用的深度探讨(让你走出经典书籍中的误区): [Re: fuliang2008] Copy to clipboard
Posted by: ranchgirl
Posted on: 2005-08-03 22:43

1) Your understaning of Pass by value is totally wrong in any sense! Please do not confuse beginners by saying "可能受c++影响太重". You don't really know c/c++.

2) There is no new definition of "pass by value" by Sun. Actually, Dr. Gosling and other Java creators are all C/C++ programmers.

3) Just for your information, another famous book "Thinking in C++" is also written by the same author: Bruce Eckel. I guess he knows a little C++ too, at least, I dare to assume that he knows no less than you. Probably, you would not think Bruce Eckel is also 严重不足, should learn C++ and Java from you. Big Smile LOL.

4) You really need re-learn the course "Programming languages". I assume you learned it before. If you did not, it is time to take the course, or buy a book now.


Q. What is the differences between pass-by-value and pass-by-reference?

A: These two will never mix!!!
Pass-by-value : You make a copy of the parameter (argument), and use it inside of the methods. The value of the parameter (argument) will not be affected outside of the method.

Pass-by-references : you do NOT make a copy of the parameter, you use the parameter itself!

Q. Why we say, in c or Java, everything is pass-by-value?
A:
In c and Java, everything is pass-by-value.

In c++ and Pascal, you can pass-by-value or pass-by-reference.

When we code in C, you pass pointers to a method, the value of pointer (address) will never change, but the value the pointer points to will change.

In language theory, C is a only-pass-by-value language. Actually, this is exactly Java does. Java Object reference is equivalent to C pointer, the difference is you cannot dereference it, which makes java safer, but less flexible.

Since in C, you can dereference a pointer, you actually can prove the pointer is passed by value. A simple test can prove that, you dereference the pointer inside/outside the method call, you will get two different values, which proves inside the method, what we are using actually a copy of the pointer, not the pointer itself. That is exactly what pass-by-value means. You make a copy of the parameter (argument), and use it inside of the methods. The value of the parameter (argument) will not be affected outside of the method.

In Java, value of an object reference is the reference. That is the source of confusion. However, if you read it twice, it only makes sense. Doesn't it?


Copied from http://bobcat.webappcabaret.net/javachina/faq/07.htm#pas_Q3

6.Re:有关java与c++引用的深度探讨(让你走出经典书籍中的误区): [Re: fuliang2008] Copy to clipboard
Posted by: ftang
Posted on: 2005-08-17 02:43

haha~~~~fuliang2008 u ar funny guy....u talk like lawyer...

7.Re:有关java与c++引用的深度探讨(让你走出经典书籍中的误区): [Re: fuliang2008] Copy to clipboard
Posted by: wonderfuture
Posted on: 2005-09-01 15:09

关于这种争论没有任何意义:引用本身是一个4字节变量,其“值”的内容是被引用对象在内存中的地址。所谓"总是按值传递" 是说,引用变量进入方法内部时,方法也要在栈中创建一个保存其4字节“值”的局部变量,但由于这个变量值与传入前的值一样——都指向同一个内存地址,引用同一个对象。"总是按值传递" 是一种内部机制,就是说,java绝对不会将一个“变量”(不是“对象”)的地址传给你,你只能获得一个变量的值。

8.Re:有关java与c++引用的深度探讨(让你走出经典书籍中的误区): [Re: fuliang2008] Copy to clipboard
Posted by: ken0719
Posted on: 2005-09-05 23:45

关于传值还是传引用,我也有着个困惑,开始学java看书的时候,知道说的是java的参数是传值,写代码验证,如果传递一个基本类型,是值传递的,如果参数是一个对象,在方法中对该句柄重新初始化一个对象,原来的对象也不会改变,但是后来发现一个问题,例如,传递一个StringBuffer类型参数,在方法中调用StringBuffer的append方法,原来的对象的内容也是会改变的,看着又像是传递引用了。

9.Re:有关java与c++引用的深度探讨(让你走出经典书籍中的误区): [Re: fuliang2008] Copy to clipboard
Posted by: ken0719
Posted on: 2005-09-05 23:46

以下是测试代码:

public class TestParameter {
public TestParameter() {
}

public static void main(String[] args) {
TestParameter tp=new TestParameter();
StringBuffer sb=new StringBuffer("java");
System.out.println("The inital value of StringBuffer is:"+sb);
tp.testNew(sb);
System.out.println("The value of StringBuffer after invoking method testNew is:"
+sb);
tp.testAppend(sb);
System.out.println("The value of StringBuffer after invoking method testAppend is:"
+sb);
}

public String testAppend(StringBuffer sb){
sb.append(",test");
System.out.println("The value of StringBuffer in method testAppend is:"+sb);
return sb.toString();

}

public String testNew(StringBuffer sb){
sb=new StringBuffer();
sb.append(",test");
System.out.println("The value of StringBuffer in method testNew is:"+sb);
return sb.toString();
}

}

10.Re:有关java与c++引用的深度探讨(让你走出经典书籍中的误区): [Re: fuliang2008] Copy to clipboard
Posted by: ken0719
Posted on: 2005-09-05 23:47

运行结果:
The inital value of StringBuffer is:java

The value of StringBuffer in method testNew is:,test

The value of StringBuffer after invoking method testNew is:java

The value of StringBuffer in method testAppend is:java,test

The value of StringBuffer after invoking method testAppend is:java,test

11.Re:有关java与c++引用的深度探讨(让你走出经典书籍中的误区): [Re: fuliang2008] Copy to clipboard
Posted by: ken0719
Posted on: 2005-09-05 23:56

从这个代码和结果中感觉java中对象的传递,传递的就是个内存指针(不是复制),也就是引用,只是如果你要对这个参数重新赋值的话,会新创建一个对象但是不改变原来的,并且使你的引用指向新创建对象,但是原来的对象还是指向原来的指针。不知道我是不是也对传值和传引用的理解有错误。

12.Re:有关java与c++引用的深度探讨(让你走出经典书籍中的误区): [Re: ken0719] Copy to clipboard
Posted by: ranchgirl
Posted on: 2005-09-07 13:21

ken0719 wrote:
关于传值还是传引用,我也有着个困惑,开始学java看书的时候,知道说的是java的参数是传值,写代码验证,如果传递一个基本类型,是值传递的,如果参数是一个对象,在方法中对该句柄重新初始化一个对象,原来的对象也不会改变,但是后来发现一个问题,例如,传递一个StringBuffer类型参数,在方法中调用StringBuffer的append方法,原来的对象的内容也是会改变的,看着又像是传递引用了。


You are not reading the document and the correct answer above, just think in the wrong direction.

Nobody can help you if you decide not to read. Sigh....

13.Re:有关java与c++引用的深度探讨(让你走出经典书籍中的误区): [Re: fuliang2008] Copy to clipboard
Posted by: ken0719
Posted on: 2005-09-07 14:51

Sorry, I make a mistake aobut what passed by value is.

"When we code in C, you pass pointers to a method, the value of pointer (address) will never change, but the value the pointer points to will change. "

14.Re:有关java与c++引用的深度探讨(让你走出经典书籍中的误区): [Re: fuliang2008] Copy to clipboard
Posted by: ranchgirl
Posted on: 2005-09-08 05:48

Haha, you got it!!!! Big Smile
Thanks!

15.Re:有关java与c++引用的深度探讨(让你走出经典书籍中的误区): [Re: fuliang2008] Copy to clipboard
Posted by: morphine
Posted on: 2005-09-09 11:34

受教了,多谢!


   Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent
Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1
客服电话 18559299278    客服信箱 714923@qq.com    客服QQ 714923