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

什么是解释?


当前回答

在Java中,你永远不会通过参考,而一个显而易见的方式是当你想从一个方法通话中返回超过一个值时。

void getValues(int& arg1, int& arg2) {
    arg1 = 1;
    arg2 = 2;
}
void caller() {
    int x;
    int y;
    getValues(x, y);
    cout << "Result: " << x << " " << y << endl;
}

有时你想在Java中使用相同的模式,但你不能;至少不是直接。

void getValues(int[] arg1, int[] arg2) {
    arg1[0] = 1;
    arg2[0] = 2;
}
void caller() {
    int[] x = new int[1];
    int[] y = new int[1];
    getValues(x, y);
    System.out.println("Result: " + x[0] + " " + y[0]);
}

正如以前的答案中所解释的那样,在Java中,你将一个指标转移到序列作为一个值进入 getValues. 这就足够了,因为方法然后改变序列元素,并且通过协议,你期望元素 0 包含回报值。

其他回答

似乎一切都被称为Java的价值,因为我试图通过下一个程序来理解。

班级S

class S{
String name="alam";
public void setName(String n){
this.name=n; 
}}

类样品

    public class Sample{
    public static void main(String args[]){
    S s=new S();
    S t=new S();
    System.out.println(s.name);
    System.out.println(t.name);
    t.setName("taleev");
    System.out.println(t.name);
    System.out.println(s.name);
    s.setName("Harry");
    System.out.println(t.name);
    System.out.println(s.name);
    }}

出口

哈里 哈里 哈里 哈里 哈里 哈里 哈里

既然我们定义了 S 类的例子变量名称与值字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符

所以我认为这就是为什么它表明Java只处理值而不是参考值。

原始变量的记忆分配可以通过此理解

这是一个非常简单的方式来理解这一点. 让我们通过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通过值。

Bob 保持他的列表,他称之为 tinyHouseAt1234Main,与相机相机,允许他在实时注意到实际房子的任何变化。

这个奇怪的副作用,通过一个列表到新的自动化服务是混乱的人谁问它是如何工作的。 事实上,什么是区别的能力远程控制机器人,改变的状态的房子在1234 Main, vs. 实际上物理上去那里,因为安妮给了你地址?

不要重复,但对于那些在阅读许多答案后仍然可能会感到困惑的人来说,有一点:

通过值在Java是不等于通过值在C++,虽然听起来像这样,这可能是为什么有混乱。

打破它:

通过值在 C++ 意味着通过对象的值(如果对象),字面上,对象的副本通过值在 Java 意味着通过对象的地址值(如果对象),而不是真正的对象的“值”(一个副本)如 C++ 通过值在 Java,在一个对象(例如 myObj.setName(“新”)在一个函数内运作的对象(例如 myObj.setName(“新”)在函数之外对对象产生影响;通过通过函数的值。

所以,朋友们,一切都只是关于术语定义的差异(通过语言),你只需要知道它是如何工作的(也许有时有点混淆它是如何称之为我承认)!

对于简单性和言语性 其通过值参考:

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
}