在 Java 中传递引用和在 C 中传递指针有什么区别?

2022-09-03 08:31:51

我已经学习了几个月的Java,现在开始学习C。

我有点困惑,我的印象是通过引用传递一个对象和传递一个指针到该对象是一回事:我认为区别在于,在Java中,所有对象的传递都是用指针自动完成的,就像在C中一样,人们必须在这里和那里洒上小星号和& 符号。最近,在谈话中,我确信有区别!

通过引用传递和传递指针有什么区别?


答案 1

Java C 都没有按引用传递。它们都是严格按值传递的。

按引用传递语义意味着,当您更改方法中参数的值时,调用方将在参数中看到该更改。

现在,你可能会想:“但Java就是这种情况!如果我在方法过程中更改了一个对象,调用方就会看到该更改。对象不是参数。该参数只是变量 - 如果更改该变量的值,调用方将看不到该值。例如:

public void foo(Object x)
{
    x = null;
}

public void caller()
{
    Object y = new Object();
    foo(y);
    // y is still not null!
}

如果参数确实是通过引用传递的,则之后将为 null。相反,的值只是一个引用,并且该引用按值传递。这是令人困惑的,因为“参考”这个词在这两个术语中都有,但它们是不同的东西。yy

你可能想看看我关于 C# 参数传递的文章,看看如果 Java 确实具有按引用传递的语义,就像 C# 在使用关键字时(并且仅当)使用关键字时所做的那样,会发生什么。ref

您可能还想查看与该主题相关的Stack Overflow答案的评论。


答案 2

我认为不同之处在于,在Java中,所有对象的传递都是用指针自动完成的,而在C中,人们必须在这里和那里实际撒上小星号和与号。

概念,这是完全正确的。如果我们是迂腐的(这是一件好事),我们甚至可以说对象在Java中根本没有传递。传递的只是“指针”,在Java中称为引用。所有间接寻址都是自动完成的。因此,当您在C中执行“objref->foo”而不是“objref.foo”并且由于使用指针而无法使用点时,在Java中,您仍然可以使用点,因为它不知道任何其他内容来访问成员。在C中,您可以传递指针(在这里,它实际上称为指针),并且可以传递对象本身,在这种情况下,将传递副本。在 C 中,您可以使用星号或“->”访问指针通过间接寻址引用的对象。在Java中,访问对象的唯一方法是使用点(objref.member)。

如果我们再次迂腐(现在再次变得更加重要),那么在Java和C中都没有“通过引用传递”。我们在Java中传递的是指向对象的引用/指针,在C中,我们要么传递对象的副本(明显情况),要么再次仅传递指向对象的指针的副本。因此,在这两种情况下 - Java和C - 我们传递的是对象的地址。不是在谈论原始Java类型,它们在Java和C中都是复制的 - 即使您也可以在C中传递它们的地址,在这方面,聚合类型(即结构)和C中的“原始类型”之间没有区别。