我一直以为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;
}

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

其他回答

Java 总是通过价值,没有例外,永远。

因此,怎样才能让任何人完全困惑,相信Java是通过参考,或者认为他们有一个Java作为通过参考的例子?关键点是Java从来没有提供直接访问对象本身的价值,在任何情况下。

因此,当呼叫一种方法时

对于原始论点(int、long等)而言,值的过渡是原始的实际价值(例如,3)。

所以,如果你有DoSomething(foo)和公共空白DoSomething(Foo foo) {.. } 两个 Foos 有复制的参考,指向相同的对象。

当然,通过值对一个对象的参考看起来非常相似(并且在实践中不可分辨的)通过对象的参考。

在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 包含回报值。

简单的计划

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 等)的函数的变化不会反映在呼叫函数中,但是当您通过对象并在函数中更改其数据会员或呼叫会员函数可以改变对象的状态时,呼叫函数会得到变化。

我会以另一种方式说:

在 Java 引用中,这些引用是通过的(但不是对象),这些引用是通过的值(引用本身是复制的,你有 2 引用作为结果,你没有控制在方法中的第 1 引用下)。

例如,在Python相同的情况,但有文章,描述他们称之为Pass-by-reference,只有原因引用被使用。

例如,使用 badSwap() 方法:

public void badSwap(int var1, int var2)
{
  int temp = var1;
  var1 = var2;
  var2 = temp;
}

当 badSwap() 返回时,作为论点过渡的变量将仍然保持其原始值。 该方法也会失败,如果我们将论点类型从 int 转换为 对象,因为 Java 通过对象参考值也。

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

图1 转移到一个方法后,对象将至少有两种参考。

Java 复制并通过参考值,而不是对象. 因此,方法操作将改变对象,因为参考指向原始对象. 但是,因为参考是复制,交换将失败。 方法参考交换,但不是原始参考。 不幸的是,在一个方法呼叫后,你只剩下未交换的原始参考。