2

我对Java不是很熟悉,我在摆弄一个简单的二叉树,遇到了一些我不明白的东西......

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

但是,如果我更改我的更改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 {
        ...
    }
4

2 回答 2

2

assuming you have declared mRoot as a Node in your class already let me answer your question.

java is always pass by value when you pass mRoot to your method you are passing bytes that are referring the object in the heap. for example when you do this with a primitive variable

int i =5;
int j=i;

the bytes stored in i is transferred to j. similarly when you do this

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

the bytes stored in the reference variable obj is getting transferred to the reference newObj. as obj holds the reference to the Object instance the same reference is held by newObj.

you can see that

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

same way

obj = new Object();
newObj  = obj;
newObj = new Object(); // this doesn't change the obj

hope you understood.

EDIT:

to answer your question in the comment, consider the following code.

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;
    }
  }

}
于 2013-11-06T05:36:02.360 回答
2

这是因为您没有mRoot在第一种情况下进行设置。即使您设置 a nodeto 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。然后您重新初始化node为新对象(例如对象 Y)。但前面的mRoot仍然指向对象 X。

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

当我们说按值传递时,对于原语,值是被复制的。但是在对象的情况下,对象引用被复制(但不是对象被复制)。因此,如果您将字符串引用传递给函数,则函数参数将仅指向相同的字符串(因为它复制了可以作为指针的对象引用)

于 2013-11-06T05:31:08.260 回答