为啥要从方法修改变量? [复制]

Posted

技术标签:

【中文标题】为啥要从方法修改变量? [复制]【英文标题】:Why is variable being modified from a method? [duplicate]为什么要从方法修改变量? [复制] 【发布时间】:2017-02-21 14:00:19 【问题描述】:

背景

我正在制作一个用于将 Python 功能添加到 Java 数组的数组工具类,我遇到了这个问题。这显然是一个简化的、更通用的版本。

问题

在这个例子中:

public class ArrayTest


    public static void main(String[] args)
    
        // initial setup
        int[] given = 1, 2, 3, 4, 5;

        // change array
        int[] changed = adjust(given);

        // these end up being the same...
        System.out.println(Arrays.toString(changed));
        System.out.println(Arrays.toString(given));
    
    private static int[] adjust(int[] a)
    
        for (int i = 0; i < a.length; i++)
        
            a[i]++;
        
        return a;
    


...为什么changedgiven 是同一个东西?

免责声明

我猜以前有人问过这个问题,但我找不到答案,所以对此我深表歉意。

【问题讨论】:

你说得对,这一定是重复的。搜索它很棘手,但我们应该能够找到它。 修改传递给方法的数组将修改该数组:***.com/questions/12757841/… 【参考方案1】:

当你这样做时

int[] given = 1, 2, 3, 4, 5;

given 的值称为对象引用。这是一个值,告诉 JVM 该数组在内存中的其他位置。 given包含 数组(就像int 一样),它包含对数组的引用(例如,像地址)。例如:

+−−−−−−−−−−−+ [给定:Ref88465]---->| (数组) | +−−−−−−−−−−−+ | 0:1 | | 1:2 | | 2:3 | | 3:4 | | 4:5 | +−−−−−−−−−−−+

当您调用adjust(given) 时,您会将given 的值的副本传递给adjust。该副本仍然指向内存中的同一位置。例如,调用adjust期间,我们有该对象引用的两个副本,都指向同一个数组:

+−−−−−−−−−−−+ [给定:Ref88465]---->| (数组) | / +−−−−−−−−−−−+ | | 0:1 | | | 1:2 | | | 2:3 | | | 3:4 | | | 4:5 | | +−−−−−−−−−−−+ [a:Ref88465]−−−−−−−+

当您更改数组的内容时,您正在修改数组的状态。当adjust 返回并将结果分配给changed 时,您有:

+−−−−−−−−−−−+ [给定:Ref88465]----->| (数组) | / +−−−−−−−−−−−+ | | 0:2 | | | 1:3 | | | 2:4 | | | 3:5 | | | 4:6 | | +−−−−−−−−−−−+ [更改:Ref88465]−+

如果您想要一个包含更改的数组的副本,您需要复制它,例如通过arraycopy。在实践中使用复制和就地更改,具体取决于用例。

【讨论】:

【参考方案2】:

您正在做的是将数组的地址发送到您的方法,因此更改的是您的原始数组,您只需返回它(数组的地址),因此您对该数组所做的任何更改(内存)将反映在两个变量中,因为它们都指向相同的内存位置

【讨论】:

在 Java 中我们不是在谈论 address,而是在谈论 reference 哦哦。不!这是参考!请遵守正确的条款。 @AmerQarabsa 引用变量保存的值允许 JVM 将该值映射到正确的对象位置。对象可以通过 JMV 在内存中移动,因此它们的地址可能会改变,但这并不意味着引用也会改变。 您正在发送参考的副本。指针可以改变它们指向的地址,这在 Java 中是被禁止的。 @AmerQarabsa:这是值的副本,就像int a = 42; int b = a;a (42) 的值复制到b 中一样。这种情况下的值为int;在 OP 的情况下,它是一个对象引用,但无论哪种方式,它都是一个值。所以“参考副本”是完全正确的。

以上是关于为啥要从方法修改变量? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 Java 方法不能更改传递的变量? [复制]

为啥我能够从在同一对象的另一个实例上调用的方法访问一个实例的私有实例变量? [复制]

为啥 Replace() 字符串方法不修改我的字符串变量?

为啥即使我修改了 lock 变量,我也会得到一个无限的 while 循环? [复制]

为啥要修改此数组? [复制]

为啥 require() 函数不接受变量? [复制]