我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。

什么是解释?


当前回答

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 描述,方法参考交换,但不是原始参考。

其他回答

Java 是值之通(stack memory)

它是如何工作的

首先,让我们明白,在哪里Java存储原始数据类型和对象数据类型。原始数据类型本身和对象参考存储在架子里.对象本身存储在架子里.这意味着,架子记忆存储原始数据类型以及对象的地址。

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 描述,方法参考交换,但不是原始参考。

Java 仅通过值,没有通过参考,例如,您可以看到下面的示例。

package com.asok.cop.example.task;
public class Example {
    int data = 50;

    void change(int data) {
        data = data + 100;// changes will be in the local variable 
        System.out.println("after add " + data);
        }

    public static void main(String args[]) {
        Example op = new Example();
        System.out.println("before change " + op.data);
        op.change(500);
        System.out.println("after change " + op.data);
    }
}

出口:

before change 50
after add 600
after change 50

正如迈克尔在评论中所说:

物品仍然通过价值,尽管它们的操作表现像通过参考。 考虑无变 人物(人){人 = 新人(); } 呼叫者对个人对象的参考将保持不变. 物品本身通过价值,但其成员可以受到变化的影响。 为了成为真实的通过参考,我们必须能够重新分配论点到一个

这是一个非常简单的方式来理解这一点. 让我们通过C++参考。

#include <iostream>
using namespace std;

class Foo {
    private:
        int x;
    public:
        Foo(int val) {x = val;}
        void foo()
        {
            cout<<x<<endl;
        }
};

void bar(Foo& ref)
{
    ref.foo();
    ref = *(new Foo(99));
    ref.foo();
}

int main()
{
   Foo f = Foo(1);
   f.foo();
   bar(f);
   f.foo();

   return 0;
}

什么是结果?

1
1
99
99

因此,在 bar() 将新值分配到输入的“参考”后,它实际上改变了从主要本身输入的值,解释了从主要打印99 的最后一个 f.foo() 呼叫。

现在,让我们看看Java说了什么。

public class Ref {

    private static class Foo {
        private int x;

        private Foo(int x) {
            this.x = x;
        }

        private void foo() {
            System.out.println(x);
        }
    }

    private static void bar(Foo f) {
        f.foo();
        f = new Foo(99);
        f.foo();
    }

    public static void main(String[] args) {
        Foo f = new Foo(1);
        System.out.println(f.x);
        bar(f);
        System.out.println(f.x);
    }

}

它说:

1
1
99
1

因此,Foo的主要引用被转移到酒吧,仍然没有改变!

这个例子清楚地表明,Java不是与C++相同的,当我们说“通过参考”。基本上,Java将“参考”作为“值”转移到功能,这意味着Java通过值。

Java 使用 pass-by-value,但效果不同的是你是否使用原始或参考类型。

当你将原始类型作为论点转移到一种方法时,它将获得原始类型的副本,而方法块内的任何变化都不会改变原始变量。

当您将参考类型作为一个论点转移到一个方法时,它仍然得到一个副本,但它是对对象的参考的副本(换句话说,您正在获得记忆地址的副本在对象所在地),因此对象中的任何变化在方法的区块内将影响原始对象在区块外。