不可变且按值传递

Posted

技术标签:

【中文标题】不可变且按值传递【英文标题】:Immutable and pass by value 【发布时间】:2012-01-05 15:26:08 【问题描述】:

我有以下代码 一个可变的 Person 类、String 和一个修改 String 和 Person 实例的方法

    class Person

int a = 8;

public int getA() 
    return a;


public void setA(int a) 
    this.a = a;


@Override
public String toString() 
    return "Person [a=" + a + "]";


  

--

public class TestMutable 
public static void main(String[] args)

    Person p = new Person();
    p.setA(34);


    String s = "bar";

             modifyObject(s, p);   //Call to modify objects

    System.out.println(s);
    System.out.println(p);





private static void modifyObject(String str, Person p)


        str = "foo";
        p.setA(45);



  

输出符合预期。它打印

           bar
          Person [a=45]

现在,我的问题是

你说 str="foo" 的地方发生了什么?

首先我们假设 s='bar' 并且数据驻留在 0x100 内存中

现在字符串的引用被传递给另一个方法,另一个方法尝试使用 s="foo" 将内存位置 (0x100) 的内容更改为 'foo'。这是正在发生的事情,还是“foo”是在不同的内存位置创建的?

java 是否按值传递引用?

【问题讨论】:

可能重复:***.com/questions/40480/is-java-pass-by-reference 【参考方案1】:

modifyObject 中,当您分配给str 时,您并没有改变str,而是将其设置为指向不同的对象。由于是按值传递的,所以你的modifyObject方法本地的str指针是mains指针的副本,所以当你更改前者时,它不会影响以后的文件。

另一方面,当涉及到p 时,modifyObject 中的那个仍然是main 中那个的副本,但是两个指针都指向内存中的同一个对象,因此如果你调用一个来自modifyObject 的方法,你实际上是在改变p 指向的东西。

【讨论】:

【参考方案2】:

Java 总是按值而不是按引用传递参数。


让我通过example 解释一下:

public class Main

     public static void main(String[] args)
     
          Foo f = new Foo("f");
          changeReference(f); // It won't change the reference!
          modifyReference(f); // It will change the object that the reference variable "f" refers to!
     
     public static void changeReference(Foo a)
     
          Foo b = new Foo("b");
          a = b;
     
     public static void modifyReference(Foo c)
     
          c.setAttribute("c");
     

我将分步骤解释:

1- 声明一个名为 f 类型为 Foo 的引用,并将其分配给一个类型为 Foo 的新对象,其属性为 "f"

Foo f = new Foo("f");

2- 在方法方面,声明了一个名为 a 的类型为 Foo 的引用,并且它最初分配给 null

public static void changeReference(Foo a)

3- 当您调用方法changeReference 时,引用a 将被分配给作为参数传递的对象。

changeReference(f);

4- 声明一个名为 b 类型为 Foo 的引用,并将其分配给一个类型为 Foo 的新对象,其属性为 "b"

Foo b = new Foo("b");

5- a = b 正在将引用 a NOT f 重新分配给其属性为 "b" 的对象。


6- 当您调用modifyReference(Foo c) 方法时,会创建一个引用c 并将其分配给具有"f" 属性的对象。

7-c.setAttribute("c");会改变引用c指向它的对象的属性,和引用f指向它的对象是同一个对象。

我希望您现在了解在 Java 中如何将对象作为参数传递:)

【讨论】:

哇!让我们把它剪下来写一本书吧:-) 解释得很好!【参考方案3】:

在这个函数中调用“modifyObject(s, p);”您正在将变量 s 的值发送到 modifyObject 方法的局部变量 str。因此创建了一个新变量,它的值发生了变化,但原始变量保持不变。

【讨论】:

【参考方案4】:

有时人们在通过引用传递时会感到困惑。可以更改引用所指的对象(给人一种传递引用的印象),但不能修改引用本身。所以它仍然是按值传递。

【讨论】:

以上是关于不可变且按值传递的主要内容,如果未能解决你的问题,请参考以下文章

对 Java 的按值传递和不变性感到困惑

python中的“引用”和C++的引用

为啥不允许将数组按值传递给 C 和 C++ 中的函数?

JavaScript 是按引用传递还是按值传递语言?

输入参数传递:是不是有有效的按值传递的大小阈值?

java的按值传递与按引用传递