【问题标题】: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 是否按值传递引用?

【问题讨论】:

标签: java parameter-passing terminology pass-by-reference pass-by-value


【解决方案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】:

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

      【讨论】:

        猜你喜欢
        • 2018-07-20
        • 1970-01-01
        • 2019-03-23
        • 2010-09-05
        • 2020-03-17
        相关资源
        最近更新 更多