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

什么是解释?


当前回答

对某些文章进行一些修正。

C 不支持通过参考,它总是通过值,C++ 支持通过参考,但不是默认情况,而且非常危险。

无论是什么值在Java:原始或地址(大约)的对象,它总是通过值。

如果一个Java对象“行事”,就像它是通过参考一样,这是一种可变性属性,与过渡机制毫无关系。

我不确定为什么这那么令人困惑,尤其是因为这么多Java“编程师”没有正式训练,因此不明白真正发生在记忆中的事情吗?

其他回答

简单的计划

import java.io.*;
class Aclass
{
    public int a;
}
public class test
{
    public static void foo_obj(Aclass obj)
    {
        obj.a=5;
    }
    public static void foo_int(int a)
    {
        a=3;
    }
    public static void main(String args[])
    {
        //test passing an object
        Aclass ob = new Aclass();
        ob.a=0;
        foo_obj(ob);
        System.out.println(ob.a);//prints 5

        //test passing an integer
        int i=0;
        foo_int(i);
        System.out.println(i);//prints 0
    }
}

从 C/C++ 程序员的观点来看,Java 使用通过值,因此对于原始数据类型(int、char 等)的函数的变化不会反映在呼叫函数中,但是当您通过对象并在函数中更改其数据会员或呼叫会员函数可以改变对象的状态时,呼叫函数会得到变化。

我只是注意到你提到我的文章。

了解这一点的关键是,这样的事情

Dog myDog;

它不是狗;它实际上是指向狗。在Java中使用“参考”这个术语是非常误导性的,这引起了大多数混乱。

这意味着,当你有

Dog myDog = new Dog("Rover");
foo(myDog);

您基本上将创建的狗对象的地址转移到 foo 方法。

public void foo(Dog someDog) {
    someDog.setName("Max");     // AAA
    someDog = new Dog("Fifi");  // BBB
    someDog.setName("Rowlf");   // CCC
}

让我们看看发生了什么。

这里是钥匙。

记住 myDog 是指标,而不是真正的狗,答案是 NO. myDog 仍然有值 42;它仍然指向原始狗(但请注意,由于“AAA”线,它的名字现在是“Max” - 仍然是相同的狗; myDog 的值没有改变)。

在 C++、Ada、Pascal 和支持 pass-by-reference 的其他语言中,您实际上可以更改已通过的变量。

void swap(int *x, int *y) {
    int t = *x;
    *x = *y;
    *y = t;
}

int x = 1;
int y = 2;
swap(&x, &y);

该功能将指标传递给数据,并跟随这些指标访问和修改这些数据。

void swap(int[] x, int[] y) {
    int temp = x[0];
    x[0] = y[0];
    y[0] = temp;
}

int[] x = {1};
int[] y = {2};
swap(x, y);

创建新点对象创建新点参考,并启动该参考到点(参考到)上以前创建的点对象. 从这里,通过点对象生活,您将通过pnt1参考访问该对象. 所以我们可以说,在Java中,您通过其参考操纵对象。

此分類上一篇

public static 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("X1: " + pnt1.x + " Y1: " +pnt1.y); 
  System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);
  System.out.println(" ");
  tricky(pnt1,pnt2);
  System.out.println("X1: " + pnt1.x + " Y1:" + pnt1.y); 
  System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);  
}

该计划的流动:

Point pnt1 = new Point(0,0);
Point pnt2 = new Point(0,0);

System.out.println("X1: " + pnt1.x + " Y1: " +pnt1.y); 
System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);
System.out.println(" ");

预计产量将是:

X1: 0     Y1: 0
X2: 0     Y2: 0

在此线上“pass-by-value”进入游戏中。

tricky(pnt1,pnt2);           public void tricky(Point arg1, Point arg2);

 arg1.x = 100;
 arg1.y = 100;

此分類上一篇

下一篇: 迷人的方法

Point temp = arg1;
arg1 = arg2;
arg2 = temp;

在这里,您首先创建一个新的 temp 点参考,将指向同一个位置,如 arg1 参考。 然后您将移动 arg1 参考,以指向同一个位置,如 arg2 参考。

从这里,迷人的方法的范围已经消失了,你不再有任何访问参考: arg1, arg2, temp. 但重要注意的是,当它们“在生活中”时,你所做的一切都会永久地影响它们所指向的对象。

X1: 0         Y1: 0
X2: 0         Y2: 0
X1: 100       Y1: 100
X2: 0         Y2: 0

斯科特·斯坦奇菲尔德先生写了一个很好的答案. 这里是你要确认的课堂,他是什么意思:

public class Dog {

    String dog ;
    static int x_static;
    int y_not_static;

    public String getName()
    {
        return this.dog;
    }

    public Dog(String dog)
    {
        this.dog = dog;
    }

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

    public static void foo(Dog someDog)
    {
        x_static = 1;
        // y_not_static = 2;  // not possible !!
        someDog.setName("Max");     // AAA
        someDog = new Dog("Fifi");  // BBB
        someDog.setName("Rowlf");   // CCC
    }

    public static void main(String args[])
    {
        Dog myDog = new Dog("Rover");
        foo(myDog);
        System.out.println(myDog.getName());
    }
}

因此,我们从主()一个名叫Rover的狗,然后我们将一个新的地址给我们通过的指标,但最终,狗的名字不是Rover,也不是Fifi,也许不是Rowlf,但Max。

我从一本关于Java认证的书中取了这个代码和解释,并做了一些小变化,我认为这是一个很好的图像,通过对象的价值。在下面的代码中,重新分配g不会重新分配f!在条()方法的结尾,创建了两个Foo对象,一个是由当地变量f和一个是由当地(论点)变量g提到的。

package test.abc;

public class TestObject {

    /**
     * @param args
     */
    public static void main(String[] args) {
        bar();
    }

    static void bar() {
        Foo f = new Foo();
        System.out.println("Object reference for f: " + f);
        f.setName("James");
        doStuff(f);
        System.out.println(f.getName());
        //Can change the state of an object variable in f, but can't change the object reference for f.
        //You still have 2 foo objects.
        System.out.println("Object reference for f: " + f);
        }

    static void doStuff(Foo g) {
            g.setName("Boo");
            g = new Foo();
            System.out.println("Object reference for g: " + g);
        }
}


package test.abc;

public class Foo {
    public String name = "";

    public String getName() {
        return name;
    }

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

}

对象参考 f: test.abc.Foo@62f72617