为什么交换功能失败? (通过值与通过vs参考)

时间:2017-03-25 23:36:04

标签: java

首先,这不是重复问题。请继续阅读,你会知道原因。

答案here,也是维基的一部分,详细解释了如何在方法参数中传递参数。我将在此处复制/粘贴它,以便读者不必来回浏览新的浏览器标签:

  

我觉得自己要争论的是"传递参考和传递价值"不是   超有帮助的。

     

如果你说," Java通过任何(参考/值)",但在   无论哪种情况,您都无法提供完整的答案。这里有一些   其他信息有助于理解什么是什么   发生在记忆中。

     

在我们进入Java实现之前,堆栈/堆上的崩溃过程:   值以一种非常有序的方式进入和离开堆栈,就像堆栈一样   在自助餐厅的盘子。堆中的内存(也称为动态   记忆)是杂乱无章的。 JVM只是找到了空间   它可以在任何地方,并释放它,因为使用它的变量是否定的   需要更长时间。

     

好。首先,本地原语进入堆栈。所以这段代码:

int x = 3;
float y = 101.1f;
boolean amIAwesome = true;
     

结果如下:

     

primitives on the stack

     

声明并实例化对象时。实际的对象还在继续   堆。什么在堆栈上?对象的地址   堆。 C ++程序员会将此称为指针,但有些Java   开发人员反对“#34;指针"”这个词是种族主义者。随你。只知道   对象的地址进入堆栈。

     

像这样:

int problems = 99;
String name = "Jay-Z";
     

a b*7ch aint one!

     

数组是一个对象,因此它也会在堆上运行。那怎么样?   数组中的对象?他们得到了自己的堆空间,而且   每个对象的地址都在数组内部。

JButton[] marxBros = new JButton[3];
marxBros[0] = new JButton("Groucho");
marxBros[1] = new JButton("Zeppo");
marxBros[2] = new JButton("Harpo");
     

marx brothers

     

那么,当你调用一个方法时会传入什么?如果你传入   对象,你实际传入的是对象的地址。   有些人可能会说"价值"地址,有些人说它只是一个   引用该对象。这是圣战之间的起源   "参考"和"价值"支持者。你所说的并不是什么意思   重要的是,你了解传入的是什么   对象的地址。

private static void shout(String name){
    System.out.println("There goes " + name + "!");
}

public static void main(String[] args){
    String hisName = "John J. Jingleheimerschmitz";
    String myName = hisName;
    shout(myName);
}
     

创建一个字符串,并在堆中分配空间,并且   字符串的地址存储在堆栈中并给出   标识符hisName,因为第二个String的地址是   与第一个相同,没有创建新的String,也没有新的堆空间   已分配,但在堆栈上创建了新标识符。然后我们打电话   shout():创建一个新的堆栈框架,并使用新的标识符name   创建并分配已存在的String的地址。

     

la da di da da da da

     

那么,价值,参考?你说"马铃薯"。

因此,根据相同的逻辑,交换功能也应该起作用。但它并没有。让我告诉你:

... main(Str..) {
String one = "one";
String two = "two";
swap (one,two);
System.out.println("outside method " + one);
System.out.println("outside method " + two);
}

swap(String o, String t) {
    String temp = o;
            o = t;
            t = temp;
    System.out.println("inside method " + o);
    System.out.println("inside method " + t);
}

这不会更改变量onetwo的值。为什么不?第二个问题:我们如何在(one)方法中更改twoswap的值?

这就是它在内存中的样子:

enter image description here

2 个答案:

答案 0 :(得分:1)

swap不起作用,因为Java按值传递方法参数,而不是通过引用传递。这不是"圣战&#34 ;;这种主张只能由不了解事实的人提出。事实上,传递参考和传值是客观可验证的事实现象。您的swap示例是Java不通过引用传递的规范证明。你引用的文章中所有多余的措辞都只是吹烟。

请记住Java所谓的"引用"实际上是一个指针。即使在支持pass-by-reference的C ++中,指针通常也是按值传递的。您必须明确要求通过引用传递它们。

Java并没有为您提供该选项。您只能通过值传递。

答案 1 :(得分:0)

您的swap()方法由于某些原因而无法正常工作。 调用swap()时,参数是对值的新引用, 所以当我在运行时调用swap(String1,String2)时,变量String1将被传递给参数中的新引用。

这样做的是,即使我们调用swap(一,二),参数也是范围内的新变量,它们对应于原始的一个和两个的值。两个分别。

这意味着当我调用swap()时,参数是变量的副本,而不是相同的变量。由于字符串是不可变的并且无法更改(仅重新分配变量),这意味着即使我调用one = "SomethingElse",这意味着引用的参数副本等于SomethingElse,而不是原始变量仍然具有其值one = "something"的{​​{1}}因为我没有重新分配one的原始引用,只是重新分配恰好指向相同值的参数变量。

要解决这个问题,你需要在没有方法调用的情况下在原始语句中执行方法代码,这样变量就是你想要的变量。