您的位置:首页 > 编程语言 > Java开发

java参数的传递方式

2015-10-13 15:08 330 查看
最近在重新学习数据结构,今天在用java实现二叉排序树的查找方法时,发现了问题(其实之前就遇到过,只不过当时没当回事)。

public boolean search(BSTNode<T> r, T element, BSTNode<T> rem){	//rem存储距离元素最近的节点,如果查找成功就是该节点
if(r == null)
return false;
else if(r.isLeaf()&&!r.data.equals(element)){
rem = r;
return false;
}
else{
int cmp = element.compareTo(r.data);
if(cmp == 0){
rem = r;
return true;
}
if(cmp < 0)
return search(r.lchild, element, rem);
if(cmp > 0)
return search(r.rchild, element, rem);

}
return false;
}


运行发现空指针异常,调试后发现问题在于调用search方法后传入的参数p(形参为rem)没有发生变化。当时很不解,说好的引用传递呢?后来上网搜索才发现问题所在。

java中其实只有值传递,没有引用传递。所谓引用传递不过是把对象的引用进行了值传递,可以通过引用的副本来操作原对象,但是不能改变原来引用所指向的对象(引用关系无法改变)。(下面的内容来自知乎)

Java 里面只有值传递,没有引用传递。当方法参数是一个对象实例时,实际上传递的是这个对象引用的拷贝,也是一种特殊的值。举例:

Object a = createObject();

methodA(a);

methodA 定义如下:

public void methodA(Object obj){

obj.doSomething();

}

在调用 methodA 的时候,拷贝了一个对对象实例(注意,对象实例本身和其引用变量是两个东西) 的引用到方法中去,这个时候,实际上是有两个引用指向这个对象实例的:

a------->ObjectInstance

obj----->ObjectInstance

所以在方法methodA内部修改了对象实例,在方法返回的时候,是可以看到修改的效果的,这样看上去像是传递了引用。

所以在定义方法时一定不要有void function(*p,...){... p = ... ...}这里*p代表对象的引用。如果要这样做,改成 类型 function(*p,...){... x = ... return x;},然后执行p = function(p);

那么问题来了,既然不能改变引用关系,那么这个功能如何实现呢?我又开始怀念C++的好了!

Update:

1.后来知道了问题解决的方案。我们如果要在一个方法中更改传入的对象引用,必须调用对象自身的变更方法,而不能使用“=”。如果使用了“=”那么变化的仅仅是对象引用副本的指向关系,原来的对象引用关系仍然存在。

2.关于改变对象的引用关系,比方说要改变引用p所指向的对象P,可以定义一个返回对象的方法,让方法返回p要指向的对象Q,执行p = function(p)即可改变p所指向的对象。在《算法》第4版中二叉树删除的操作是用到了这个技巧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: