凡是说Java对象传的是引用,简直一派胡言,尤其误导我这种Java初学者,更严重的是以前用过C++的Java初学者。
我们都知道Java建立对象一般都是需要这样的格式:
Object obj = new Object(“初始化”);
但是在C++中则是可以这样写:
Object obj = Object(“初始化”);
少了new,为什么会这样呢?
因为Java对于声明一个对象建立的是一个指针,相当于C++的这样:
Object *obj = new Object(“初始化”);
这下看上去就一样了,事实上就是这样。给函数传递参数时,两种语言没有多少区别。我们先看一个C++例子(为了简化代码,突出重点,变量直接public了):
#include <stdio.h> class MyTest
{
public:
int x;
MyTest(int x)
{
this->x = x;
}
}; void func(MyTest *&test); int main()
{
MyTest *test = new MyTest();
printf("调用前 : %d\n", test->x);
func(test);
printf("调用后 : %d\n", test->x);
return ;
}
C++代码
很多Java书上说Java中类的对象作为函数参数时传递的是引用,我们就可以这样定义C++的func函数,模拟Java书上所说的传递引用的行为:
void func(MyTest *&test)
{
test = new MyTest();
}
C++的func()函数
函数体就一行,这时执行main函数的输出是:
调用前 : 3
调用后 : 4
这个结果在任何C++初学者看来都很显然。
然后我们写一个“完全一样”的Java版本:
public class MyTest {
public int x;
public MyTest(int x) {
this.x = x;
}
}
Java的MyTest类
public class Main { public static void main(String[] args) {
MyTest test = new MyTest(3);
System.out.println("调用前 : " + test.x);
func(test);
System.out.println("调用后 : " + test.x);
} private static void func(MyTest test) {
test = new MyTest(4);
}
}
Java的main与func函数
这下输出却另我们大失所望:
调用前 : 3
调用后 : 3
竟然不一样,说好的传引用呢?为什么形参的改动没有影响到实参呢?简直了。为什么跟C++这样写效果一样啊:
void func(MyTest *test)
{
test = new MyTest();
}
C++没有引用的func函数
所以Java完全没有引用这种东西!一切都是值传递,我查资料得出的结论是:C++只是把引用符号(&)解析成了指针,也就相当于这样写func函数:
void func(MyTest **test)
{
*test = new MyTest();
}
C++指向指针的指针
这就是为什么做到了引用,其实传的还是值,只不过是传的指针的指针,就算是这样,传的还是这个指针的副本,只是里面保存的内容一样而已。
我被误导了很久,因为这样写Java的func函数可以:
private static void func(MyTest test) {
test.x = 4;
}
Java的func函数
但是这样却不行:
private static void func(MyTest test) {
test = new MyTest(4);
}
Java的func函数
所以标题写的比较偏激,表达一下纠结的心情。我个人认为正确的说法应该是:Java是值传递,类对象变量都是一个对象指针,作为参数传到函数中跟传基本类型一样,都是复制了一份副本传递的,所以可以改变其成员变量的值,但不能改变其自身。希望跟我一样的初学者没有在某些书的误导下陷入歧途!