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

什么是解释?


当前回答

您可以通过值(4,5) 您可以通过地址(0xF43A)

Point p = Point(4,5);

Point *x = &p;

它保留了 4 位比特,并存储了 0xF43A。

Point &y = p;

它保留了 4 位比特,并存储了 0xF43A。

在指标的情况下,你必须使用 -> 访问会员,在参考情况下你必须使用.. 如果你想交换原始的值,那么你可以做 tmp=a; a=b; b=tmp;在参考情况下和 tmp=*a; *b=tmp; *a=tmp为指标。

因此,Java通过原始值和对象的参考值,Java复制值来实现这一点,但C++是这样做的。

为了完整性:

Point p = new Point(4,5);

如果你想改變記憶體位置這樣

void swap(int& a, int& b) {
    int *tmp = &a;
    &a = &b;
    &b = tmp;
}

然后你会发现你走进你的硬件的限制。

其他回答

它是原始值或参考值的副本,如果是原始值,它是价值的比特的副本,如果是对象,它是参考值的副本。

public class PassByCopy{
    public static void changeName(Dog d){
        d.name = "Fido";
    }
    public static void main(String[] args){
        Dog d = new Dog("Maxx");
        System.out.println("name= "+ d.name);
        changeName(d);
        System.out.println("name= "+ d.name);
    }
}
class Dog{
    public String name;
    public Dog(String s){
        this.name = s;
    }
}

使用 Java PassByCopy:

名称= Maxx 名称= Fido

原始粘贴类和线条是不可变的,因此使用这些类型的任何例子都不会像其他类型/对象一样工作。

Pass By Reference 收到的函数值是通话者所使用的对象的参考。 通话者所指的对象的任何函数都将被通话者看到,并将从那时起与这些变化进行操作。

正如这些定义所表明的那样,参考通过值是毫无意义的,如果我们要接受这个定义,那么这些术语就变得毫无意义,所有语言都只是通过值。

因此,有了这个理解,我们可以看看Java,并看到它实际上有两种。所有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

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

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

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]