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

什么是解释?


当前回答

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

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
}

其他回答

理解它在两个步骤:

您无法更改对象本身的参考,但您可以使用此已过的参数作为对象的参考。

如果您想要更改参考背后的值,您只会在同一名称“d”的字符串上宣布一个新的变量。

public static void foo(Dog d) {
  d.Name = "belly";
  System.out.println(d); //Reference: Dog@1540e19d

  d = new Dog("wuffwuff");
  System.out.println(d); //Dog@677327b6
}
public static void main(String[] args) throws Exception{
  Dog lisa = new Dog("Lisa");
  foo(lisa);
  System.out.println(lisa.Name); //belly
}

我在这里创建了一个专门为任何编程语言提出这些问题的条纹。

Java 也被提及,这里是简短的概述:

Java 通过它的参数值“值”是Java 唯一的方式将一个参数转换为一个方法,使用从所提供的对象作为参数的方法将改变对象,因为参考指向原始对象(如果该方法本身改变某些值)。

Java,当然,毫无疑问,是“通过价值”。 此外,由于Java是(主要)对象导向和对象与参考工作,它很容易被困惑,并认为它是“通过参考”

但要测试它是否真的通过值或通过参考,你可以使用原始类型和参考:

@Test
public void sampleTest(){
    int i = 5;
    incrementBy100(i);
    System.out.println("passed ==> "+ i);
    Integer j = new Integer(5);
    incrementBy100(j);
    System.out.println("passed ==> "+ j);
}
/**
 * @param i
 */
private void incrementBy100(int i) {
    i += 100;
    System.out.println("incremented = "+ i);
}

产量是:

incremented = 105
passed ==> 5
incremented = 105
passed ==> 5

因此,在两种情况下,任何在方法中发生的事情都不会改变真正的对象,因为对象的价值已经过去了,而不是对象本身的参考。

但是,当你将自定义对象转移到一种方法,而一种方法并改变它时,它也会改变真正的对象,因为即使你通过了对象,你也将其参考作为一种价值转移到一种方法。

@Test
public void sampleTest2(){
    Person person = new Person(24, "John");
    System.out.println(person);
    alterPerson(person);
    System.out.println(person);
}

/**
 * @param person
 */
private void alterPerson(Person person) {
    person.setAge(45);
    Person altered = person;
    altered.setName("Tom");
}

private static class Person{
    private int age;
    private String name; 

    public Person(int age, String name) {
        this.age=age;
        this.name =name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("Person [age=");
        builder.append(age);
        builder.append(", name=");
        builder.append(name);
        builder.append("]");
        return builder.toString();
    }

}

在这种情况下,产量是:

Person [age=24, name=John]
Person [age=45, name=Tom]

在所有的答案中,我们看到Java通过价值,或者正如Gevorg所写的那样:“通过复制变量的价值”,这就是我们应该始终记住的想法。

在Java中,你总是通过复制论点,即你总是在函数中创建一个新的值例子,但有些行为会让你认为你正在通过参考。

此分類上一篇: [ref 1]

void incrementValue(int inFunction){
  inFunction ++;
  System.out.println("In function: " + inFunction);
}

int original = 10;
System.out.print("Original before: " + original);
incrementValue(original);
System.out.println("Original after: " + original);

We see in the console:
 > Original before: 10
 > In Function: 11
 > Original after: 10 (NO CHANGE)

以 [ref 2] 的例子

顯示優雅的機制觀點 max 5 min

(按参考通行) pass-by-copy-of-the-variable-值

void incrementValu(int[] inFuncion){
  inFunction[0]++;
  System.out.println("In Function: " + inFunction[0]);
}

int[] arOriginal = {10, 20, 30};
System.out.println("Original before: " + arOriginal[0]);
incrementValue(arOriginal[]);
System.out.println("Original before: " + arOriginal[0]);

We see in the console:
  >Original before: 10
  >In Function: 11
  >Original before: 11 (CHANGE)

复杂物体本身正在复制,但内部参考正在保持。

此分類上一篇: [ref 3]

package com.pritesh.programs;

class Rectangle {
  int length;
  int width;

  Rectangle(int l, int b) {
    length = l;
    width = b;
  }

  void area(Rectangle r1) {
    int areaOfRectangle = r1.length * r1.width;
    System.out.println("Area of Rectangle : " 
                            + areaOfRectangle);
  }
}

class RectangleDemo {
  public static void main(String args[]) {
    Rectangle r1 = new Rectangle(10, 20);
    r1.area(r1);
  }
}

我想分享的最后一件事是讲座的这个时刻:记忆分配,我认为它非常有用,以了解Java通过值或更为“通过复制变量的值”如Gevorg所写的。

Java 通过原始类型为值和类型为参考

现在,人们喜欢无限地争论是否“通过参考”是正确的方式来描述Java et al. 实际上做什么。

通过一个对象不会复制对象,转移到函数的对象可以由函数修改其成员,转移到函数的原始值不能由函数修改。

在我的书中,它被称为通过参考。

布莱恩·比(Brian Bi) - 哪种编程语言通过参考?