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

什么是解释?


当前回答

不要重复,但对于那些在阅读许多答案后仍然可能会感到困惑的人来说,有一点:

通过值在Java是不等于通过值在C++,虽然听起来像这样,这可能是为什么有混乱。

打破它:

通过值在 C++ 意味着通过对象的值(如果对象),字面上,对象的副本通过值在 Java 意味着通过对象的地址值(如果对象),而不是真正的对象的“值”(一个副本)如 C++ 通过值在 Java,在一个对象(例如 myObj.setName(“新”)在一个函数内运作的对象(例如 myObj.setName(“新”)在函数之外对对象产生影响;通过通过函数的值。

所以,朋友们,一切都只是关于术语定义的差异(通过语言),你只需要知道它是如何工作的(也许有时有点混淆它是如何称之为我承认)!

其他回答

我们有2个不同的术语(Call-by-Value/Call-by-Reference)但至少有3(!)不同的方式处理上述数据,当将其转移到一个方法:

我们的数据是复制的,复制加到一个方法. 复制的变化不会在外面传播.(想想一个 int 在 Java 或 C++ 或 C#.) 一个指标(记忆地址)我们的数据加到方法而不是. 我们的数据的变化加到外面传播. 我们也可以指向一些新的例子,让我们的原始数据危害。

在 OO 世界中, #1 是 Call-by-Value 和 #2 是 Call-by-Reference. 但是,由于我们只有两个条件为三个选项,没有两个条件之间的明确定义,由于选项 #3 。

“为什么Java开发人员会坚持自己的术语?”

“有没有解决这个混乱的办法?”

最终,不管我们称之为什么,因为只要我们彼此理解,没有混乱。

Pass By Reference 收到的函数值是通话者所使用的对象的参考。 通话者所指的对象的任何函数都将被通话者看到,并将从那时起与这些变化进行操作。

正如这些定义所表明的那样,参考通过值是毫无意义的,如果我们要接受这个定义,那么这些术语就变得毫无意义,所有语言都只是通过值。

因此,有了这个理解,我们可以看看Java,并看到它实际上有两种。所有Java原始类型总是通过值,因为你收到一个复印件的呼叫器的对象,并且不能修改他们的复印件。

我遇到了类似的问题. 这个关于圈子的故事对我来说是一个具体的答案. 我想添加到答案. 希望它能帮助那些有类似问题的人。

https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html

在方法中,循环起初指 myCircle. 该方法改变了对象的 x 和 y 坐标,循环参考(即 myCircle)为 23 和 56, 相应. 这些变化将持续,当方法返回. 然后循环被分配一个参考一个新的循环对象与 x = y = 0. 这个重新分配没有永久性, 但是,因为参考通过了值

Java 使用 pass-by-value,但效果不同的是你是否使用原始或参考类型。

当你将原始类型作为论点转移到一种方法时,它将获得原始类型的副本,而方法块内的任何变化都不会改变原始变量。

当您将参考类型作为一个论点转移到一个方法时,它仍然得到一个副本,但它是对对象的参考的副本(换句话说,您正在获得记忆地址的副本在对象所在地),因此对象中的任何变化在方法的区块内将影响原始对象在区块外。

例如,使用 badSwap() 方法:

public void badSwap(int var1, int var2)
{
  int temp = var1;
  var1 = var2;
  var2 = temp;
}

当 badSwap() 返回时,作为论点过渡的变量将仍然保持其原始值。 该方法也会失败,如果我们将论点类型从 int 转换为 对象,因为 Java 通过对象参考值也。

public void tricky(Point arg1, Point arg2)
{
  arg1.x = 100;
  arg1.y = 100;
  Point temp = arg1;
  arg1 = arg2;
  arg2 = temp;
}
public static void main(String [] args)
{
  Point pnt1 = new Point(0,0);
  Point pnt2 = new Point(0,0);
  System.out.println("X: " + pnt1.x + " Y: " +pnt1.y); 
  System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);
  System.out.println(" ");
  tricky(pnt1,pnt2);
  System.out.println("X: " + pnt1.x + " Y:" + pnt1.y); 
  System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);  
}

如果我们执行这个主要()方法,我们会看到以下输出:

X: 0 Y: 0
X: 0 Y: 0
X: 100 Y: 100
X: 0 Y: 0

图1 转移到一个方法后,对象将至少有两种参考。

Java 复制并通过参考值,而不是对象. 因此,方法操作将改变对象,因为参考指向原始对象. 但是,因为参考是复制,交换将失败。 方法参考交换,但不是原始参考。 不幸的是,在一个方法呼叫后,你只剩下未交换的原始参考。