Java浅层和深层复制JLS

时间:2011-09-21 15:58:30

标签: java deep-copy shallow-copy jls

  

可能重复:
  Java pass by reference issue

在下面的代码中,将调用methodA,然后将methodB的调用委托给methodBmethodA使用字符串文字“bbb”分配输入参数,但是,回到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"); } } ,字符串文字不在那里,JLS的哪一部分定义了这种行为?

{{1}}

2 个答案:

答案 0 :(得分:4)

这是传递值与传递引用问题。 Java仅通过值传递。当你打电话

methodB(a)

引用a被复制;在methodB的上下文中,a是一个与methodA中具有相同值的不同变量。因此,当您在methodB中进行更改时,a中的methodA仍然指向原始字符串。

这里发挥的另一个问题是字符串是不可变的,所以一旦设置了String就不能改变它的值。来自文档。

  

字符串是不变的;他们的价值观无法改变   创建

你能做的是

a = methodB();

并在"bbb"中返回methodB。没有理由通过a,因为你没有对它进行操作;我认为你只是试图在调用a的上下文中尝试更改methodB,这是你无法做到的。

最后,JLS的相关部分是8.4.1,其中说明了

  

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

答案 1 :(得分: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
}