一个 'void' 方法何时影响参数,何时影响原始对象?

8

我刚开始学习编程,也是第一次使用这个网站,如果我有什么失误请谅解。我遇到了一个麻烦,不知道如何正确地在这里发布我的代码。

package tester;
import java.util.*;
public class Mainclass2 {
    public static void main(String[] args) {

        int y = 3; 
        int[] x = {1, 2, 3, 4};

        editnumbersArray(x);
        editnumbersNotArray(y);

        System.out.println(x[2]); **//now this was changed from 3 to 9...**
        System.out.println(y);    //but this one went unchanged.

    }

    //this accepts 'x[]' into the 'a[]' parameter.
    public static void editnumbersArray(int[] a){
        a[2] = 9;  **//<---why does this one CHANGE the actual x[2] instead of just a[2]?**
    }

    //this accepts 'y' into the 'a' parameter.
    public static void editnumbersNotArray(int a){
        a = 9;  **//<--while this one only changes 'a' instead of 'y'?**
    }

}

所以我的问题基本上是在评论中输入的。为什么传递到方法中的数组会改变原始数组(x[])的值,而传递到其他方法中的int却不会改变呢?我相信这是一个简单的答案,但是当我进行调查时,我无法弄清楚要搜索什么。我不知道这叫什么,所以我搜索的一切都引导我走了错误的方向。谢谢任何帮助!
编辑:感谢那个用地址比喻的例子!这绝对是你可以向我解释的最好方式。所以基本上当你将一个数组传递到参数中时,它传递的是一个引用,而不是实际的值?因此,当我在我的方法内进行调整时,它会更改数组正在引用的任何内容?
我注意到这也发生在列表中。因此,列表实际上并没有按值传递?似乎数组/列表本身只是被传递进来进行编辑,无论我在方法中给它命名什么(在这种情况下是a[])。
编辑:http://javadude.com/articles/passbyvalue.htm 这个页面真正澄清了它。很抱歉发布了重复的问题。问题在于我不知道自己想问什么。我甚至从未听说过这些术语“按值/引用传递”,所以现在我知道了。

1
这个问题已经以很多形式被问过了,以下是其中一个更好的回答:https://dev59.com/d2ox5IYBdhLWcg3wIRD3#9404727 - Perception
可能是Java是按引用传递吗?的重复问题。 - user395760
2个回答

13

在Java中,更改参数本身的值永远不会影响参数,因为所有参数都是按值传递的。但是,请看这个方法:

public static void editnumbersArray(int[] a){
    a[2] = 9;
}

该赋值语句并不会改变参数的值。变量a仍然是同一个引用,指向同一个数组,只是改变了数组内部的内容。

想象一下,如果我在一张纸上写下我的家庭地址,那么你对那张纸做什么都不会改变我的住址。但是如果你到了我的家里,将门漆成了绿色,而且根本没有改变那张纸的任何内容,我看到这种变化。

区分不同概念非常重要:

  • 变量是一个命名的存储位置;它保存一个值,这个值总是原始值(例如int)或引用。在上面的例子中,那张纸就像变量。
  • 引用只是一个值,允许您导航到一个对象。它不是对象本身。就像纸上的地址一样。
  • 对象包含其他变量。可能有几个变量,它们的值都是对同一个对象的引用。就像我例子中的房子:我可以在几张纸上写下我的地址,但只有一个房子。

数组是一个充当其他变量容器的对象。因此,a的值只是对数组的引用。


1
你们刚刚让我大开眼界。那太有道理了,谢谢!希望有一天我也能像你们一样为这个网站贡献答案。现在我甚至还不能“点赞”哈哈。 - Ryan
1
@RyanKlassy:每个人都要从某个地方开始,理解这一点是Java中最重要的早期步骤之一。突然间,“一切”可能会更加清晰明了——什么是将一个变量的值赋给另一个变量,垃圾回收等等。 - Jon Skeet

2
Java对于所有东西都使用传值(你要搜索的内容)。这基本上意味着它会复制参数并将其传递给方法。这意味着您无法通过使用“=”运算符来更改指向某个位置的内容。
这就是为什么(int a)版本不会更改a的原因。
但是,在对象或数组的情况下,它不会创建对象或数组的副本,而是创建指向对象或数组的引用的副本。这意味着您有两个变量,原始变量和在您的示例中(int[] a)的一个变量,两者都指向内存中的同一位置。对任何一个变量所做的更改都会影响另一个变量。
传值,传引用和按引用传值是您想要搜索了解更多信息的类型。

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