我试图理解Java中的参数传递。 Stackoverflow上有一些答案,但不清楚。 Evaluation Strategy页面非常具有技术性,因此我对此并不了解。这个答案很有帮助,但我不明白其含义:Is Java “pass-by-reference” or “pass-by-value”?
我理解Java使用Call by Sharing,但我不确定它与Call by Reference的区别。我不确定这是否正确,你能查看我的答案吗?
共享步骤
1)主程序调用一个方法并传递一个参数
2)评估参数中的表达式并确定其类型。结果将分配给Argument变量。
按值调用
3)不考虑类型,制作参数值的COPY并传递给方法。
4)形式参数接收包含参数COPY的变量
5)正式论证对副本进行更改
6)实际论点是不变的。
按参考号召集
3)不考虑类型,制作论证的地址的COPY并传递给该方法。
4)形式参数接收参数的存储位置的参考
5)Formal Argument和Actual Argument指向相同的值。两者都可以修改值/对象
6)方法可以在不受限制的情况下改变形式参数。当方法结束时,这些更改将在参数中看到。
通过共享呼叫(Java)
3)不考虑类型,进行参数地址的复制并传递给方法。
4)?
5)?
6)?
我知道Java在参数传递中如何处理原始类型和对象之间存在差异,有人可以通过解释原因填写这些空白吗?
答案 0 :(得分:1)
按值调用表示
按参考呼叫意味着
现在,我将跳过“分享呼叫”,因为它没有明确的含义。
它如何在Java中工作
如您所见,Java匹配Call by Value案例。但是,要真正理解这一点,您必须了解Java如何处理引用。为此,请考虑此课程
public class Foo {
private String value;
public Foo(String value) {
this.value = value;
}
public String get() {
return value;
}
public void set(String value) {
this.value = value;
}
}
和此代码段:
Foo actual = new Foo("foo"); // 1
// 2
Foo formal = actual; // 3
formal.set("bar"); // 4
// 5
actual.get(); // returns "bar" // 6
如您所见,formal
中对象的更改已应用于actual
中的对象,因为formal
指向与actual
相同的对象。赋值Foo formal = actual;
确实复制了引用,它没有复制对象。
现在,让我们看看另一个代码示例:
Foo actual = new Foo("foo"); // 1
// 2
Foo formal = actual; // 3
formal = new Foo("bar"); // 4
// 5
actual.get(); // returns "foo" // 6
正如您所看到的,对formal
的更改尚未应用于actual
,因为formal
中指向actual
中对象的引用已被覆盖通过引用一个新对象。赋值Foo formal = actual;
确实复制了引用,它没有将指针复制到actual
。
现在,我谈到了作业,因为我认为作业非常明确。现在的观点是,这与方法调用的行为完全相同:调用方法时,将计算出的实际参数赋值给形式参数,参见第3行。但是,形式参数不在方法完成后分配回实际参数,参见第5行。
这称为“共享呼叫”的原因是,您没有传递实际参数的深层副本。因此,在调用者和被调用者之间共享对象。如果对象包含可变状态(如Foo
),则调用方可以看到应用于方法中该可变状态的所有更改。请注意区别:传递的对象的更改是可见的,更改正式参数的参考目标是不可见的。
最后,关于基元的快速说明:上面的代码不需要为基元更改。这意味着,只有类型Foo
才会更改为boolean
。其他一切都是一样的。因此,行为再次与赋值相同:复制该值。由于原始值不能包含可变状态,因此毫无疑问这是Call by Value。
答案 1 :(得分:-1)
我理解Call By Sharing是这样的:
使用Value类型,直接复制实际值,并将新副本传递给被调用者。原始值无法修改。
使用引用类型,将复制对值的实际引用,并将新副本传递给被调用者。可以修改引用的对象,但重新分配不会修改原始引用。
如果使用传递的引用重新分配,则在callee中创建一个新对象,返回调用者将反映最初传递的对象。在被调用者中创建的对象应该超出范围并标记为收集。