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

什么是解释?


当前回答

Java 按值传输参考。

因此,你不能改变通过的参考。

其他回答

Java 总是使用 Call by Value. 这意味着该方法获得所有参数值的副本。

考虑下列三种情况:

1、试图改变原始变量

public static void increment(int x) { x++; }

int a = 3;
increment(a);

x 将复制一个值,并将增加 x,一个将保持相同的值

(二)试图改变对象的原始领域

public static void increment(Person p) { p.age++; }

Person pers = new Person(20); // age = 20
increment(pers);

p 将复制个体的参考值,并将增加年龄领域,变量是指相同的对象,所以年龄改变。

(三)试图改变参考变量的参考值

public static void swap(Person p1, Person p2) {
    Person temp = p1;
    p1 = p2;
    p2 = temp;
}

Person pers1 = new Person(10);
Person pers2 = new Person(20);
swap(pers1, pers2);

呼叫交换 p1 后,p2 复制 pers1 和 pers2 的参考值与值交换,因此 pers1 和 pers2 仍然相同。

因此,您只能在将参考值复制到该对象时更改对象的字段。

这是一个非常简单的方式来理解这一点. 让我们通过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. 通过使用 pass-by-values 的参数不会影响/改变原始变量. 在下一个程序中,我们启动了一种称为 'x' 的变量,并使用 pass-by-value 技术来证明变量的值如何保持不变。

public class Main 
{    
   public static void main(String[] args)
   { 
       //Original value of 'x' will remain unchanged 
       // in case of call-by-value 
   
       int x = 5;
       System.out.println( "Value of x before call-by-value: " + x);
       // 5

       processData(x);
       System.out.println("Value of x after call-by-value: " + x);
       // 5
   }
   public static void processData(int x) 
   { 
       x=x+10;          
   }
}

通过值和通过参考值之间的差异

什么是 Pass by Value?

通过值,函数参数的值将复制到记忆中的另一个位置,在函数内访问或修改变量时,它只会访问复制。

通过参考,记忆地址转移到该函数,换句话说,函数可以访问实际变量。

定义

Pass by value 是指将函数参数值复制到另一个变量的机制,而 pass by reference 是指将实际参数转移到函数的机制。

变化

目前的参数

查看此代码. 此代码不会扔 NullPointerException... 它将打印“Vinay”

public class Main {
    public static void main(String[] args) {
        String temp = "Vinay";
        print(temp);
        System.err.println(temp);
    }

    private static void print(String temp) {
        temp = null;
    }
}

如果 Java 通过参考,则应该将 NullPointerException 扔下来,因为参考设置为 Null。

Java 只通过值,这是一个很简单的例子来验证这一点。

public void test() {
    MyClass obj = null;
    init(obj);
    //After calling init method, obj still points to null
    //this is because obj is passed as value and not as reference.
}
private void init(MyClass objVar) {
    objVar = new MyClass();
}