【问题标题】:"pass by value" or "pass by reference" in Java? [duplicate]Java中的“按值传递”或“按引用传递”? [复制]
【发布时间】:2021-11-04 20:21:32
【问题描述】:

我正在尝试了解如何在 Java 中传递参数。例如,我有以下代码:

class Runner{
    public static void main(String[] args)
    {
        Integer test = new Integer(20);
        updateObject(test);
        System.out.println(test);
    }
    public static void updateObject(Integer test)
    {
        test = 50;
    }
}

它打印“20”。

但是,如果我像这样使用自己的类而不是 Integer:

import java.util.*;
class Test {
    int num;
    Test(int x){
        num = x;
    }
    Test(){
        num = 0;
    }
}

class Runner{
    public static void main(String[] args)
    {
        Test test = new Test(20);
        updateObject(test);
        System.out.println(test.num);
    }
    public static void updateObject(Test test)
    {
        test.num = 50;
    }
}

在这种情况下 println 打印“50”。

为什么在第一种情况下我的参数没有改变,但在第二种情况下却被改变了?

【问题讨论】:

标签: java


【解决方案1】:

在java中它总是按值传递参数。如果您处理类的实例,那么棘手的事情是引用类型,当您作为参数传递给方法时,对实例的引用按值传递,这意味着对该对象的引用将被复制到方法参数,所以引用作为价值本身。

在您的第一个示例中,当您执行 Integer test = new Integer() 时,您创建了一个新的整数实例,并将它的引用设置为测试变量。这里棘手的部分是,整数是不可变类型,即使您引用整数也没有合法的方法来更改它的内容(反射是可能的,但是在大多数情况下使用反射来改变不可变是不好的)

在你的第一个例子中,你做test = 50,这个东西叫做autobox,Integer仍然是不可变的,而java在这里做了什么,它将你的代码编译为test = new Integer(50)(有一些优化,但我们现在跳过它们),因此它将创建值为 50 的整数的新实例,并将方法 updateObject 的变量引用覆盖到该新实例,Integer(20) 仍然存在于内存中的某处,但是方法 updateObject 中的变量测试不'没有参考它了。但是,您在方法 main 中有另一个测试变量,并且该变量仍然保持对第一个 Integer 实例的引用,编号为 20。

关于您的第二个示例,您现在创建了可变类型,并执行 line: test.num = 50 - 它会保持对您的类实例的引用不变,但它会改变类的字段。在引用同一实例的两个静态方法中的第二个示例测试变量中。这就是它打印相同值的原因。

希望它会说清楚。

【讨论】:

    猜你喜欢
    • 2012-03-12
    • 2013-09-15
    • 2013-01-21
    • 2012-01-16
    • 2012-10-14
    • 2014-09-10
    • 2019-05-07
    • 2013-12-02
    • 1970-01-01
    相关资源
    最近更新 更多