【问题标题】:Java shallow and deep copying JLS [duplicate]Java浅拷贝和深拷贝JLS [重复]
【发布时间】:2011-09-21 15:58:30
【问题描述】:

可能重复:
Java pass by reference issue

在我下面的代码中,methodA 将被调用,然后将调用委托给 methodB,在此过程中,methodB 将输入参数分配给字符串文字“bbb”,但是,返回到 methodA ,字符串文字不存在,JLS 的哪个部分定义了这种行为?

package sg.java.test2;

public class TestApple {
    public static void main(String args[]){
        methodA();
    }

    public static void methodA(){
        String a = null; 

        methodB(a);

        System.out.println(a);
    }

    public static void methodB(String a){
        a = new String("bbb");
    }
}

【问题讨论】:

    标签: java deep-copy shallow-copy jls


    【解决方案1】:

    这是按值传递与按引用传递的问题。 Java 仅按值传递。当你打电话时

    methodB(a)

    引用a 被复制;在methodB 的上下文中,a 是一个不同的变量,其值与methodA 中的值相同。所以当你在methodB中改变它时,methodA中的a仍然指向原来的String。

    这里涉及的另一个问题是字符串是不可变的,因此一旦设置了字符串,您就无法更改它的值。来自文档。

    字符串是常量;它们的值在它们被更改后不能更改 已创建。

    你能做的是

    a = methodB();

    并在methodB 中返回"bbb"。没有理由将a 传入,因为您没有对其进行操作;我认为您这样做只是为了尝试在调用 methodB 的上下文中更改 a,这是您无法做到的。

    最后,JLS的相关部分是8.4.1,上面写着

    当调用方法或构造函数时(第 15.12 节), 实际参数表达式初始化新创建的参数 变量,每个声明的类型,在执行主体之前 方法或构造函数。出现在 DeclaratorId 可以用作方法主体中的简单名称或 构造函数来引用形参。

    【讨论】:

    • 谢谢,另外,如果我试图传递的参数不是字符串,并且是可变的,比如普通的域对象,上述情况是否仍然成立?
    • 正确下巴。我为您的回答添加了一个示例。
    • 感谢好友的提醒。
    【解决方案2】:

    Java 是按值传递,而不是按引用传递。

    方法签名是这个的简写:

    methodB() {
        String a = arguments[0];
    

    即这是一个差异参考。当您分配给“a”时,您分配给作为方法签名的一部分创建的引用“a”,而不是您在包含对 methodB() 的调用的代码块中声明的“a”。

    但是,如果它是一个对象,您可以修改该值。

    class MyObj {
        String prop;
        public MyObj(String s) { prop = s; }
        public MyObj() { }
    }
    
    public void methodB(MyObj o) {
        o.prop = "foo";
    }
    
    public void methodA() {
        MyObj a = new MyObj();
        System.out.println(a.prop); // null
        methodB(a);
        System.out.println(a.prop); // foo
    }
    

    【讨论】:

    • java 是按值传递该死的!!
    • 抱歉,意思是说不是通过引用传递...已修复
    • 为什么a.foo在从methofB(a)回来后给出一个“foo”..
    • @chin 因为methodB 设置a.foo = 'foo'
    • @hvgotcodes 因为我又犯了一个错误并输入了“foo”而不是“prop”...睡眠不足,咖啡太少。
    猜你喜欢
    • 1970-01-01
    • 2011-03-24
    • 2011-02-09
    • 2012-04-12
    • 2015-01-13
    • 2016-05-07
    • 2017-10-14
    • 2012-04-13
    • 1970-01-01
    相关资源
    最近更新 更多