Java按引用传递

33

这两段代码有什么区别:

代码A:

Foo myFoo;
myFoo = createfoo();

从哪里开始

public Foo createFoo()
{
   Foo foo = new Foo();
   return foo;
}

与Code B相比的Visual Studio Code:

Foo myFoo;
createFoo(myFoo);

public void createFoo(Foo foo)
{
   Foo f = new Foo();
   foo = f;
}

这两段代码之间有什么区别吗?


7
这里没有“按引用传递”的语法。它是按值传递,而该值是一个引用。B代码无法编译,即使编译了也不会改变myFoo的值。 - harold
4个回答

204

Java总是按值传递参数,而不是按引用传递。


让我通过一个例子来解释:

public class Main
{
     public static void main(String[] args)
     {
          Foo f = new Foo("f");
          changeReference(f); // It won't change the reference!
          modifyReference(f); // It will modify the object that the reference variable "f" refers to!
     }
     public static void changeReference(Foo a)
     {
          Foo b = new Foo("b");
          a = b;
     }
     public static void modifyReference(Foo c)
     {
          c.setAttribute("c");
     }
}

我会分步骤解释这个问题:
  1. Declaring a reference named f of type Foo and assign it to a new object of type Foo with an attribute "f".

    Foo f = new Foo("f");
    

    enter image description here

  2. From the method side, a reference of type Foo with a name a is declared and it's initially assigned to null.

    public static void changeReference(Foo a)
    

    enter image description here

  3. As you call the method changeReference, the reference a will be assigned to the object which is passed as an argument.

    changeReference(f);
    

    enter image description here

  4. Declaring a reference named b of type Foo and assign it to a new object of type Foo with an attribute "b".

    Foo b = new Foo("b");
    

    enter image description here

  5. a = b is re-assigning the reference a NOT f to the object whose its attribute is "b".

    enter image description here


  6. As you call modifyReference(Foo c) method, a reference c is created and assigned to the object with attribute "f".

    enter image description here

  7. c.setAttribute("c"); will change the attribute of the object that reference c points to it, and it's same object that reference f points to it.

    enter image description here

我希望你现在明白了Java中传递对象作为参数的工作原理 :)

你能对比一下“按引用传递”会是什么样子吗?我理解的是,“按值传递”是传递 f 所引用的对象的内存地址。在 changeReference 中,a 是一个新变量,它引用相同的内存地址,改变 a 的值(或所引用的内存地址)只会改变 a 指向的内容而不是 f。如果是“按引用传递”,那么 f 将被传递进来,所以 a = f,改变 a 的值(或所引用的内存地址)将会改变 f - Clarence Liu

10

由于Java严格遵循“传值而非传引用”的原则,即使是对象的引用也是按值传递的,因此第二段代码将无法按预期工作。请参见右侧的“相关”部分,了解有关此问题的众多讨论。


2

将方法参数视为其自己的变量声明。如果您用一段代码块替换方法调用,则它看起来像这样:

Foo myFoo;
{                      //Method call starts here
    Foo foo;
    foo = myFoo;
    Foo f = new Foo();
    foo = f;
}                      //Method call ends here

即使方法参数与另一个变量具有相同的名称,方法参数仍然是它自己的唯一引用,只有方法知道。这就是Eng.Fouad上面所说的内容。

1
另一个重要的点是您应该知道传递到方法中的对象类型,无论它是可变对象还是不可变对象。如果您传递一个不可变对象,例如字符串,它将创建另一个副本并进行修改。更改不会反映在原始副本中。

不,该语言中没有“可变”或“不可变”的概念。因此,在它们传递的方式上没有区别。“更改不会反映到您的原始副本。”根据定义,不可变对象是指没有“更改”的方法,因此这个说法没有意义。 - newacct

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接