Java并通过引用传递

时间:2013-11-06 05:28:48

标签: java

我对Java并不十分熟悉,我正在摆弄一个简单的二叉树,遇到了一些我不理解的东西......

在以下代码段中,Add()传递AddHelper()个数字和对根节点mRoot的引用。但是,即使在第一次调用AddHelper()

之后,mRoot也始终为null

但是,如果我改变,我改变AddHelper()使得它直接使用mRoot(而不是通过引用传入),那么它可以工作......我不明白为什么/如何会有所不同,功能上。

Node mRoot;

public void Add( int num ) {
    AddHelper(num, mRoot);
}

private void AddHelper( int num, Node node ){
    // if I change 'node' to 'mRoot', it works. why?
    if ( node == null ) {
        node = new Node(num);
    }
    else {
        ...
    }

2 个答案:

答案 0 :(得分:2)

这是因为您没有在第一种情况下设置mRoot。即使您将node设置为new Node(num);,也不会设置mRoot。设置mRoot:

if ( node == null ) {
        node = new Node(num);
        this.mRoot = node; //depending on your logic
    }
    else {
        ...
    }

Jave总是以值传递。例如,mRoot指向对象X.当您将mRoot传递给AddHelper时,现在node将指向对象X.然后您重新初始化{{1}到新的对象(比如对象Y)。但是之前的node仍指向对象X.

因此,您需要将mRoot设置回对象Y.

当我们说通过值时,对于基元,值被复制。但是对于Objects,会复制对象引用(但不会复制对象)。因此,如果将String引用传递给函数,则函数参数将仅指向相同的String(因为它复制了可以作为指针的对象引用)

答案 1 :(得分:2)

假设您已在课堂上宣布mRootNode已让我回答您的问题。

mRoot传递给您的方法时,

java总是按值传递,您传递的是引用堆中对象的字节。例如,当您使用原始变量

执行此操作时
int i =5;
int j=i;

i中存储的字节将传输到j。同样,当你这样做时

Object obj = new Object();
Object newObj = obj;

存储在引用变量obj中的字节将转移到引用newObj。因为obj持有对Object实例的引用,newObj保持相同的引用。

你可以看到

i = 5;
j=i;
j=10; // this doesn't change the i value

同样的方式

obj = new Object();
newObj  = obj;
newObj = new Object(); // this doesn't change the obj
希望你理解。

修改

在评论中回答您的问题,请考虑以下代码。

class Sample {
  Object originalObj;
  public static void main(String[] args) {
   System.out.println(originalObj); // prints null

   tryToCreateInstance(originalObj);
   System.out.println(originalObj); // still prints null

   createInstance(originalObj)
   System.out.println(originalObj); // prints the object hashcode

  originalObj = returnInstance(originalObj);//returns the same reference as originalObj
                                          //is already initialized, if it had been null
                                          // this would have returned a new object
   System.out.println(originalObj); // prints the object hashcode
  }

  public void tryToCreateInstance(Object obj1){
    if(obj1==null) {
       obj1 = new Object(); // relate this with my answer above 
                            // this wont change what originalObj refers
    }
  }

  public void createInstance(){
    if(obj==null) {
       originalObj = new Object(); // refers to the instance variable originalObj
                                   // hence will affect what originalObj refers
    }
  }

  public Object returnInstance(Object obj1) {
    if(obj1==null) {
       return new Object(); // returns a new object
    }
    else {
      return obj1;
    }
  }

}