我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。

什么是解释?


当前回答

“pass-by-value”和“pass-by-reference”是指变量;“pass-by-value”是指变量的值转移到函数/方法;“pass-by-reference”是指该变量的参考转移到函数;“pass-by-reference”是指变量的值转移到函数;“pass-by-reference”是指变量的值转移到函数。

它如同这样:

public static void main(String[] args) {
    Dog aDog = new Dog("Max");
    Dog oldDog = aDog;

    // we pass the object to foo
    foo(aDog);
    // aDog variable is still pointing to the "Max" dog when foo(...) returns
    aDog.getName().equals("Max"); // true
    aDog.getName().equals("Fifi"); // false
    aDog == oldDog; // true
}

public static void foo(Dog d) {
    d.getName().equals("Max"); // true
    // change d inside of foo() to point to a new Dog instance "Fifi"
    d = new Dog("Fifi");
    d.getName().equals("Fifi"); // true
}

同样:

public static void main(String[] args) {
    Dog aDog = new Dog("Max");
    Dog oldDog = aDog;

    foo(aDog);
    // when foo(...) returns, the name of the dog has been changed to "Fifi"
    aDog.getName().equals("Fifi"); // true
    // but it is still the same dog:
    aDog == oldDog; // true
}

public static void foo(Dog d) {
    d.getName().equals("Max"); // true
    // this changes the name of d to be "Fifi"
    d.setName("Fifi");
}

有关参考通行和值通行的更多信息,请参见以下答案: https://stackoverflow.com/a/430958/6005228. 这更详细地解释了两者背后的语法和历史,并解释了为什么Java和许多其他现代语言似乎在某些情况下都会做两件事。

其他回答

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

}

我将在步骤中解释这一点:

宣布一个参考名为Foo类型,并将其分配给一个新的Foo类型对象与属性“f”。Foo f =新Foo(“f”);从方法侧,一个Foo类型的参考名称A被宣布,它最初被分配为零。

我希望你现在明白如何通过对象作为论点在Java工作:)

我做了这个小图表,显示了数据是如何创建和通过的

此分類上一篇

注意:原始值作为值传递,该值的第一个参考是方法的论点。

这意味着:

您可以在函数内更改 myObject 的值 但您不能更改 myObject 引用到,函数内,因为点不是 myObject 记住,点和 myObject 是引用,不同引用,但是,这些引用在同一个新点(0,0)

Java 通过值的参数,但对于对象变量,值基本上是对象的参考。

public static void dummyIncrease(int[] x, int y)
{
    x[0]++;
    y++;
}
public static void main(String[] args)
{
    int[] arr = {3, 4, 5};
    int b = 1;
    dummyIncrease(arr, b);
    // arr[0] is 4, but b is still 1
}

main()
  arr +---+       +---+---+---+
      | # | ----> | 3 | 4 | 5 |
      +---+       +---+---+---+
  b   +---+             ^
      | 1 |             | 
      +---+             |
                        |
dummyIncrease()         |
  x   +---+             |
      | # | ------------+
      +---+      
  y   +---+ 
      | 1 | 
      +---+ 

以下是更准确的定义:

通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用通用

因此,在 C/C++ 中,您可以创建一个函数,可以使用参数交换两个值:

void swap(int& a, int& b) 
{
    int tmp = a; 
    a = b; 
    b = tmp; 
}

你可以看到它有一个独特的参考 a 和 b,所以我们没有一个副本,tmp 只保留独特的参考。

Java 中的相同函数没有副作用,通过参数就像上面的代码一样,没有参考。

虽然Java使用指标/参考,但参数不是独特的指标,在每个属性中,它们被复制,而只是作为C/C++分配。

正如许多人之前提到的那样,Java总是有价值的。

下面是另一个例子,这将帮助你理解差异(经典交换例子):

public class Test {
  public static void main(String[] args) {
    Integer a = new Integer(2);
    Integer b = new Integer(3);
    System.out.println("Before: a = " + a + ", b = " + b);
    swap(a,b);
    System.out.println("After: a = " + a + ", b = " + b);
  }

  public static swap(Integer iA, Integer iB) {
    Integer tmp = iA;
    iA = iB;
    iB = tmp;
  }
}

印刷:

前: a = 2, b = 3 后: a = 2, b = 3

这是因为 iA 和 iB 是新的本地参考变量,具有相同值的过去参考(他们的点到 a 和 b 相应)。因此,试图改变 iA 或 iB 的参考将仅在本地范围内变化,而不是在该方法之外。