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

什么是解释?


当前回答

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

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

打破它:

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

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

其他回答

Java 以值传输对象的参考。

因此,如果对参考论点所指出的对象进行任何修改,则将反映在原始对象上。

但是,如果引用论点指向另一个对象,则原始引用将指向原始对象。

区别,或可能只是我记得我曾经像原始海报一样的印象是这样的:Java总是通过价值,Java中的所有对象(除了原始对象)都是参考。

“pass-by-value”和“pass-by-reference”是指变量;“pass-by-value”是指变量的值转移到函数/方法;“pass-by-reference”是指该变量的参考转移到函数;“pass-by-reference”是指变量的值转移到函数;“pass-by-reference”是指变量的值转移到函数。

它如同这样:

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
}

同样:

public static void main(String[] args) {
    Dog aDog = new Dog("Max");
    Dog oldDog = aDog;

    foo(aDog);
    // when foo(...) returns, the name of the dog has been changed to "Fifi"
    aDog.getName().equals("Fifi"); // true
    // but it is still the same dog:
    aDog == oldDog; // true
}

public static void foo(Dog d) {
    d.getName().equals("Max"); // true
    // this changes the name of d to be "Fifi"
    d.setName("Fifi");
}

有关参考通行和值通行的更多信息,请参见以下答案: https://stackoverflow.com/a/430958/6005228. 这更详细地解释了两者背后的语法和历史,并解释了为什么Java和许多其他现代语言似乎在某些情况下都会做两件事。

第二步,请记住,当您将对象转移到一种方法时,您将转移到对象参考,而不是对象本身。

现在,想想一个对象的参考/变量是什么:

1. Person person;
2. person = new Person("Tom");
3. changeName(person);
4.
5. //I didn't use Person person below as an argument to be nice
6. static void changeName(Person anotherReferenceToTheSamePersonObject) {
7.     anotherReferenceToTheSamePersonObject.setName("Jerry");
8. }

发生了什么?

变量人是创建的行 #1 它是零的开始. 一个新人对象是创建的行 #2,存储在记忆中,变量人是给予的参考人对象. 也就是说,其地址. 让我们说 3bad086a. 保持对象的地址的变量人是转移到函数行 #3. 在行 #4 你可以听到沉默的声音 查看其地址。

一张照片值得一千个字:

此分類上一篇

请注意,另一个ReferenceToTheSamePersonObject射线是指向对象而不是变量人!

您总是输入参考值的比特的副本!

Java 是 pass-by-value 因为在一个方法中,你可以随心所欲地修改所提到的对象,但无论你尝试多么艰难,你永远不会能够修改过去的变量,这将保持参考(不 p _ _ _ _ _ _ _ )相同的对象,不管是什么!



Java 始终是 pass-by-value,参数是经过的变量的副本,所有对象都是用参考来定义的,参考是存储一个记忆地址的变量,其中对象在记忆中。

查看评论以了解执行中发生了什么;跟随数字,因为它们显示执行的流动。

class Example
{
    public static void test (Cat ref)
    {
        // 3 - <ref> is a copy of the reference <a>
        // both currently reference Grumpy
        System.out.println(ref.getName());

        // 4 - now <ref> references a new <Cat> object named "Nyan"
        ref = new Cat("Nyan");

        // 5 - this should print "Nyan"
        System.out.println( ref.getName() );
    }

    public static void main (String [] args)
    {
        // 1 - a is a <Cat> reference that references a Cat object in memory with name "Grumpy"
        Cat a = new Cat("Grumpy");

        // 2 - call to function test which takes a <Cat> reference
        test (a);

        // 6 - function call ends, and <ref> life-time ends
        // "Nyan" object has no references and the Garbage
        // Collector will remove it from memory when invoked

        // 7 - this should print "Grumpy"
        System.out.println(a.getName());
    }
}