Java和按引用传递

Java和按引用传递,java,Java,我对Java不是很熟悉,我在摆弄一个简单的二叉树,遇到了一些我不懂的东西 在下面的代码段中,Add()传递一个数字和对根节点mRoot的引用。但是,即使在第一次调用AddHelper() 但是,如果我更改I changeAddHelper()使它直接使用mRoot(而不是通过引用传入),那么它就可以工作了。。。我不明白这在功能上有什么不同 Node mRoot; public void Add( int num ) { AddHelper(num, mRoot); } private

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

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

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

这是因为您在第一种情况下没有设置
mRoot
。即使您正在将
节点设置为
新节点(num),您没有设置
mRoot
。要设置mRoot,请执行以下操作:

if ( node == null ) {
        node = new Node(num);
        this.mRoot = node; //depending on your logic
    }
    else {
        ...
    }
哈维总是被价值观所忽略。例如,
mRoot
指向对象X。当您将
mRoot
传递给
AddHelper
时,现在
节点将指向对象X。然后您将
节点重新初始化为新对象(比如对象Y)。但是前面的
mRoot
仍然指向对象X

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


当我们说“按值传递”时,对于基本体,值被复制。但对于对象,将复制对象引用(但不会复制对象)。因此,如果将字符串引用传递给函数,函数参数将仅指向同一字符串(因为它复制了对象引用,对象引用可以被视为指针)

这是因为在第一种情况下没有设置
mRoot
。即使您正在将
节点设置为
新节点(num),您没有设置
mRoot
。要设置mRoot,请执行以下操作:

if ( node == null ) {
        node = new Node(num);
        this.mRoot = node; //depending on your logic
    }
    else {
        ...
    }
哈维总是被价值观所忽略。例如,
mRoot
指向对象X。当您将
mRoot
传递给
AddHelper
时,现在
节点将指向对象X。然后您将
节点重新初始化为新对象(比如对象Y)。但是前面的
mRoot
仍然指向对象X

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


当我们说“按值传递”时,对于基本体,值被复制。但对于对象,将复制对象引用(但不会复制对象)。因此,如果将字符串引用传递给函数,函数参数将只指向同一字符串(因为它复制了对象引用,对象引用可以被视为指针)

假设您已将
mRoot
声明为类中的
节点,我来回答您的问题

java总是按值传递当您将
mRoot
传递给您的方法时,您正在传递引用堆中对象的字节。例如,当您使用基元变量执行此操作时

int i =5;
int j=i;
存储在
i
中的字节被传输到
j
。同样,当你这样做的时候

Object obj = new Object();
Object newObj = obj;
存储在参考变量
obj
中的字节将被传输到参考
newObj
。当obj持有对
对象的引用时,
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;
    }
  }

}

假设您已经将
mRoot
声明为类中的
节点
,那么让我回答您的问题

java总是按值传递当您将
mRoot
传递给您的方法时,您正在传递引用堆中对象的字节。例如,当您使用基元变量执行此操作时

int i =5;
int j=i;
存储在
i
中的字节被传输到
j
。同样,当你这样做的时候

Object obj = new Object();
Object newObj = obj;
存储在参考变量
obj
中的字节将被传输到参考
newObj
。当obj持有对
对象的引用时,
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;
    }
  }

}

我懂了。。。所以整个过程都崩溃了,因为我传递了一个空对象,根据定义,它指向nothing,而我不能为nothing赋值。是吗?不,这不是事实。可以将对象分配给空引用。检查我编辑的回答,但如果不明确地为originalObj分配对象,您仍然无法为它分配任何内容,这就是我的意思。如果originalObj作为参数传入时为null,则不能将对象作为参数分配给originalObj,它将保持null。你必须以某种方式拥有“originalObj=something”。你现在是…:)很高兴你能理解。。但是我不能将某物赋值给nothing是不对的,因为你可以将一个对象赋值给一个空的引用。当然,我可能可以用更好的措辞:P谢谢!我懂了。。。所以整个过程都崩溃了,因为我传递了一个空对象,根据定义,它指向nothing,而我不能为nothing赋值。是吗?不,这不是事实。可以将对象分配给空引用。检查我编辑的回答,但如果不明确地为originalObj分配对象,您仍然无法为它分配任何内容,这就是我的意思。如果originalObj作为参数传入时为null,则不能将对象作为参数分配给originalObj,它将保持null。你必须以某种方式拥有“originalObj=something”。你现在是…:)很高兴你能理解。。但是我不能将某物赋值给nothing是不对的,因为你可以将一个对象赋值给一个空的引用。当然,我可能可以用更好的措辞:P谢谢!