我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。
什么是解释?
我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。
什么是解释?
当前回答
Java 使用 pass-by-value,但效果不同的是你是否使用原始或参考类型。
当你将原始类型作为论点转移到一种方法时,它将获得原始类型的副本,而方法块内的任何变化都不会改变原始变量。
当您将参考类型作为一个论点转移到一个方法时,它仍然得到一个副本,但它是对对象的参考的副本(换句话说,您正在获得记忆地址的副本在对象所在地),因此对象中的任何变化在方法的区块内将影响原始对象在区块外。
其他回答
只需显示对比,请比较以下 C++ 和 Java 剪辑:
在 C++ 中: 注意: 坏代码 - 记忆泄漏! 但它证明了这一点。
void cppMethod(int val, int &ref, Dog obj, Dog &objRef, Dog *objPtr, Dog *&objPtrRef)
{
val = 7; // Modifies the copy
ref = 7; // Modifies the original variable
obj.SetName("obj"); // Modifies the copy of Dog passed
objRef.SetName("objRef"); // Modifies the original Dog passed
objPtr->SetName("objPtr"); // Modifies the original Dog pointed to
// by the copy of the pointer passed.
objPtr = new Dog("newObjPtr"); // Modifies the copy of the pointer,
// leaving the original object alone.
objPtrRef->SetName("objRefPtr"); // Modifies the original Dog pointed to
// by the original pointer passed.
objPtrRef = new Dog("newObjPtrRef"); // Modifies the original pointer passed
}
int main()
{
int a = 0;
int b = 0;
Dog d0 = Dog("d0");
Dog d1 = Dog("d1");
Dog *d2 = new Dog("d2");
Dog *d3 = new Dog("d3");
cppMethod(a, b, d0, d1, d2, d3);
// a is still set to 0
// b is now set to 7
// d0 still have name "d0"
// d1 now has name "objRef"
// d2 now has name "objPtr"
// d3 now has name "newObjPtrRef"
}
在Java,
public static void javaMethod(int val, Dog objPtr)
{
val = 7; // Modifies the copy
objPtr.SetName("objPtr") // Modifies the original Dog pointed to
// by the copy of the pointer passed.
objPtr = new Dog("newObjPtr"); // Modifies the copy of the pointer,
// leaving the original object alone.
}
public static void main()
{
int a = 0;
Dog d0 = new Dog("d0");
javaMethod(a, d0);
// a is still set to 0
// d0 now has name "objPtr"
}
Java 只有兩種通過: 根據內置類型的價值,並根據對象類型的指標的價值。
我看到所有的答案都是相同的:通过值。 然而,最近的布莱恩·戈茨关于Valhalla项目的更新实际上会以不同的方式回答:
事实上,这是一个常见的“gotcha”问题,关于Java对象是否通过值或参考,答案是“也不”:对象参考通过值。
您可以在这里阅读更多: 瓦尔哈拉州 部分 2: 语言模型
编辑:Brian Goetz是Java语言建筑师,领导项目如Project Valhalla和Project Amber。
Edit-2020-12-08: 瓦尔哈拉的最新状态
Book book = new Book("Effective Java");
在上面的例子中,参考变量是“书”存储在堆积中。 由新运营商创建的例子 ->新书(“有效Java”)存储在Heap中. ref变量“书”有在Heap中分配的对象地址。
此分類上一篇
public class PrimitiveTypeExample {
public static void main(string[] args) {
int num = 10;
System.out.println("Value before calling method: " + num);
printNum(num);
System.out.println("Value after calling method: " + num);
}
public static void printNum(int num){
num = num + 10;
System.out.println("Value inside printNum method: " + num);
}
}
考虑,例如通过一个定义阶级的对象作为论点的例子。
此分類上一篇
此分類上一篇
因此,当任何东西作为方法论时,它总是是Stack实体 - 无论是原始还是参考变量. 我们永远不会通过在Heap中存储的东西. 因此,在Java,我们总是通过值在Stack中,它通过值。
对于简单性和言语性 其通过值参考:
public static void main(String[] args) {
Dog aDog = new Dog("Max");
Dog oldDog = aDog;
// we pass the object to foo
foo(aDog);
// aDog variable is still pointing to the "Max" dog when foo(...) returns
aDog.getName().equals("Max"); // true
aDog.getName().equals("Fifi"); // false
aDog == oldDog; // true
}
public static void foo(Dog d) {
d.getName().equals("Max"); // true
// change d inside of foo() to point to a new Dog instance "Fifi"
d = new Dog("Fifi");
d.getName().equals("Fifi"); // true
}
Java 以参考方式操纵对象,而所有对象变量都是参考。
例如,使用 badSwap() 方法:
public void badSwap(int var1, int
var2{ int temp = var1; var1 = var2; var2 =
temp; }
public void tricky(Point arg1, Point arg2)
{ arg1.x = 100; arg1.y = 100; Point temp = arg1; arg1 = arg2; arg2 = temp; }
public static void main(String [] args) {
Point pnt1 = new Point(0,0); Point pnt2
= new Point(0,0); System.out.println("X:
" + pnt1.x + " Y: " +pnt1.y);
System.out.println("X: " + pnt2.x + " Y:
" +pnt2.y); System.out.println(" ");
tricky(pnt1,pnt2);
System.out.println("X: " + pnt1.x + " Y:" + pnt1.y);
System.out.println("X: " + pnt2.x + " Y: " +pnt2.y); }
如果我们执行这个主要()方法,我们会看到以下输出:
X: 0 Y: 0 X: 0 Y: 0 X: 100 Y: 100 X: 0 Y: 0
该方法成功地改变了 ofpnt1 的值,尽管它通过了值;但是,pnt1 和 pnt2 的交换失败了! 这是混乱的主要来源. 在 themain() 方法中,pnt1 和 pnt2 只是对象参考。 当你 passpnt1 和 pnt2 到 tricky() 方法时,Java 通过了值的参考,就像其他参数一样。
Java 复制并通过参考值,而不是对象. 因此,方法操纵将改变对象,因为参考指向原始对象. 但因为参考是复制,交换将失败. 如图 2 描述,方法参考交换,但不是原始参考。