【问题标题】:Why do arrays change in method calls?为什么数组在方法调用中会发生变化?
【发布时间】:2011-08-19 21:18:05
【问题描述】:

当我这样写时:

public class test {

    void mainx()
    {
        int fyeah[] = {2, 3, 4};
        smth(fyeah);
        System.out.println("x"+fyeah[0]);
    }

    void smth(int[] fyeah)
    {
        fyeah[0] = 22;
    }
}

它打印 x22;

当我这样写时:

public class test {

    void mainx()
    {
        int fyeah = 5;
        smth(fyeah);
        System.out.println("x"+fyeah);
    }

    void smth(int fyeah)
    {
        fyeah = 22;
    }
}

它不打印 x22,而是打印 x5。

为什么在第二个版本函数中,值没有变化?它是否仅更改数组元素的值?

【问题讨论】:

标签: java arrays


【解决方案1】:

第一个示例中的fyeah 变量包含对数组的引用(不是数组),而第二个示例中的fyeah 整数包含整数.

由于 Java 按值传递所有内容,因此将发生以下情况:

数组情况下:数组引用的副本将被发送,原始数组将被更改。

int情况下:整数的副本会被改变,而原来的整数不会改变。

【讨论】:

  • A copy of the array reference will be sent,但是这个副本不还是参考吗?我真的对此感到困惑
  • @Eng.Fouad,你明白了。将发送参考副本。
【解决方案2】:

这是因为您的 int 是一个原始类型,而 smth 方法创建了一个本地副本,这就是它无法按您想要的方式打印的原因。对象也是按值传递的,但是是指向内存中指针的值。因此,当它发生更改时,指针会在两个方法中保持不变,您会看到更改。 Read More Here

【讨论】:

    【解决方案3】:

    好的。 java 中的 int (实际上是所有具有严格数据类型的语言)是原始数据类型。它只是该数据类型的单个变量。在java中,这意味着它通过值传递给方法。因此,当您传入参数时,会创建所传递变量的副本。方法中发生的任何操作都作用于该副本而不是传递的变量。

    实际上,在 java 中,一切都是按值传递的,但用我接下来要说的内容来深入了解这实际上是如何的细节似乎是不可取的。

    使用数组...它是原始数据类型 int 的变量集合。因此,数组的整个副本实际上并不仅仅是对存储数组的内存的引用的副本。所以是的,数组中 int 的值是从方法中的操作更改的。

    简而言之,方法不要使用方法中的操作更改基元(int、float、double、long、char)的外部值,如果您愿意,您必须将这些操作的结果值返回给调用者获得它。操作确实会更改大多数对象以及基元数组的值。希望有帮助。真的不知道能达到多低的水平。也许其他人可以清楚地解释为什么它的价值。我“明白”了它,但发现很难帮助其他人理解。

    【讨论】:

      【解决方案4】:

      从内存的角度思考:让我们分析你的第一个程序 -

      mainx 中,fyeahints 的数组,因此它是一个引用(如果可能的话,它是一个指针)。此引用指向堆内存中存储ints 的实际数组的位置。假设在地址 100。从这里连续定位的是三个整数(假设从地址 100 开始,104 和 108 分别是 2 ,3 和 4 )。

      现在你调用你的方法smth 并传递引用。在该方法中,还有一个名为fyeah 的引用(int 数组类型)。这个fyeahmainx 方法中的fyeah 引用完全不同。现在,当您调用smth 并从mainx 传递fyeah 时,smth 方法中的fyeah 被初始化为指向同一位置(即内存地址100) 当您访问 fyeah 的 0 元素并为其分配值 22 时,它会到达内存位置 100 并将该值 22 写入那里。当您返回 mainx 方法时,fyeah 引用仍然指向内存地址 100。但该位置的值现在是 22。因此,当您从 fyeah 访问第一个元素时,您会得到该值在mainx

      现在,您的第二个程序。您的 mainx 方法声明了一个 int (不是一个数组,而是一个简单的 int )并将其设置为 5。这个 fyeah 变量是在堆栈上而不是在堆上创建的。 5 的值存储在堆栈中。现在你调用smth 并传递这个变量。在方法 smth 中,您再次按名称声明 int 变量 fyeah(作为正式方法参数)。同样,这与mainx 方法的fyeah 不同,并且此fyeah 也在堆栈上创建。此变量将初始化为值5,从您传递给fyeahfyeah 复制过来smth作为论据。现在请注意,fyeah variables 上有两个不同的副本,都在 stack 上,并且都是 5。现在您将 smth 中的 fyeah 赋值为 22。这不会影响 fyeahmainx 方法,所以当您返回 mainx 并访问 fyeah 时,您会看到 5。

      【讨论】:

      • 我觉得这个答案更完整/全面..
      【解决方案5】:

      int 是一个值类型,所以 5 直接传递给 smth 只能修改本地副本。另一方面,数组是引用类型,因此可以修改该数组的元素。

      【讨论】:

        【解决方案6】:

        从技术角度看,我想说的是

            fyeah[0] = 22;
        

        正在改变(指向的对象)fyeah的内容,而

            fyeah = 22;
        

        正在改变(变量)fyeah本身。
        另一个例子:

        void smth(Person person) {
            person.setAge(22);
        }
        

        在改变人的(内容)的同时

        void smth(Person person) {
            person = otherPerson;
        }
        

        正在更改变量 person - Person 的原始实例仍然未更改(并且,由于 Java 是传值,因此调用代码中的变量不会被此方法更改)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-12-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-31
          相关资源
          最近更新 更多