【问题标题】:changing address of object in Java (pass-by-value again??)在 Java 中更改对象的地址(再次按值传递??)
【发布时间】:2014-09-17 13:58:50
【问题描述】:

在我发布我的问题之前,我已经阅读了以下关于 java-pass-by-value 的优秀文章。 我确信我已经很好地理解了它。

  1. Is Java "pass-by-reference" or "pass-by-value"?
  2. http://www.javaworld.com/article/2077424/learn-java/does-java-pass-by-reference-or-pass-by-value.html

我的问题与 Java 与支持 pass-by-reference 的其他语言的并列比较有关(C++ 可能是)。

Java 的情况下,您有一个句柄(引用)指向位置A 中的对象。因此可以修改对象本身。但是无法更改对象位置本身。 即存储在内存地址 0X945 中的对象不能更改为 0X948。

C++等语言中,您可以选择pass-by-valuepass-by-reference。 (它在程序员的手中对吗?)。因此可以正确更改对象在内存空间中的位置吗?

P.S:我在 Java 方面有很好的背景,但在 C++ 方面。所以我上面的观点可能是错误的。 我在上面引用的文章 1 中声称,Java 中没有指针的概念。我不知道这是真的吗? (那为什么NullPointerException存在)

编辑: 考虑这个例子:

void swap(Object A,Object B) {
  Object temp=B;
  Object B=A;
  Oject A=temp;
}

当我在 Java 中调用 swap(A,B) 等方法时,没有任何反应 但在 C++ 中(我想),交换发生了。这可能意味着我正在正确更改内存中对象的位置?

【问题讨论】:

  • Java总是按值传递。
  • @ElliottFrisch:是的,这完全在我的脑海中根深蒂固。但我的问题是可以将对象的位置从内存地址 A 更改为内存地址 B。我认为这在 C++ 等支持引用传递的语言中是可能的吗?
  • 没有。这在 Java 中是不可能的,在 C++ 中也是不可能的。
  • 如果您传递对指针的引用,则可以在 C++ 中更改对象的位置。 AFAIK 在 java 中不存在等效的功能,但是您可以添加一个间接级别 - 传递(按值)对对象的引用,该对象具有对有问题的对象的引用。这将让您分配目标对象的新实例并让调用者知道它。
  • 由于我不懂C++,请见谅。但我认为 swap(Object A, Object B) 在 C++ 中有效,因为您可以交换对象的位置,这在 Java 中是不可能的。那么传递引用与传递值有什么不同呢?

标签: java c++ pointers pass-by-reference pass-by-value


【解决方案1】:

在 java 中甚至 - 对对象的引用是按值传递的。 即,一切都是 按值传递。接下来,

您可以选择按值传递或按引用传递。 (它在程序员的手中对吗?)。 正确的。但是你不能在 Java 中做到这一点。

存储在内存地址 0X945 中的对象不能更改为 0X948。 你不能在 java 和 C++ 中这样做。

NullPointerException 当您尝试访问不存在的东西的属性/方法时抛出(null)。即,当需要对象的实例时,引用指向 null

 Object o = null;
 o.toString()  --> NPE. o points to null.

【讨论】:

  • +1 用于回答实际问题。如果您在需要引用对象时尝试使用空值,则会引发 NullPointerException。有关可能导致此问题的一些情况的列表,请参阅 API 文档:docs.oracle.com/javase/7/docs/api/java/lang/…
  • 那么传递引用有什么不同呢?在按引用而不是按值传递的情况下,可以将存储在内存地址中的对象更改为不同的位置。请更正..
  • 没有。在pass-by-reference 中,我会将引用传递给对象。因此,您可以实际处理原始对象。在按值传递中,您传递对象的值(而不是实际对象的引用)。在 java 中,您所做的是按值传递引用,因此您可以访问实际对象。检查thisthis
  • 即使按值传递,您也可以处理原始对象。传递了一个引用的副本,它仍然指向同一个对象。我会查看您提供的链接。但是你能解释一下为什么 swap(Object A, Object B) 在 C++ 中有效,而在 Java 中无效?谢谢
  • @brainstorm - 它也可以在 java 中工作。只是您不需要交换功能。你可以用任何方法做temp=AA=BB=temp。在这里,您只是重新分配和交换 references 到对象。
【解决方案2】:

所以在 C++ 中,传递引用意味着你传递对象本身,以便它可以在交换方法中重新分配

在 C++ 中,按引用传递,swap(Object &A, Object &B) 似乎接近 java 的按值传递。

在 Java 中,Object A 是一个对象的引用,默认情况下是 null。因为Object 已经是一个引用,所以当这个引用被复制时,它是按值传递的。

在 C++ 中,Object A 是 Object 的一个实例,并且始终是唯一的对象。由于Object 是一个实例,因此您使用Object& 通过引用传递,因为Object 没有传递,而是对它的引用。

【讨论】:

  • 在 C++ 中,您仍然可以通过 swap(object* A, object* B) 传递对象本身,对吗?在某些方面,我遗漏了一些东西,因为在处理对象时,按引用传递和按引用传递值有何不同(很明显,使用原语)。
  • @brainstorm Object* 是一个指针,它可能是一个对象。这个指针必须是非常量的,所以你不能做Object A, B; swap(&A, &B);
  • 当你在 C++ 中使用Object &a, Object &b,然后你在里面做a=b;,你将a 的“内容”替换为b 的内容。 a 仍然具有相同的地址,但它现在是不同的对象。我相信它被称为“价值语义”。 Java 中没有相应的语义。在 java 中,a=b; 意味着变量 a 现在与变量 b 引用同一个对象 - 根本不是同一件事。
  • 是否将传递引用视为传递位置的内存地址而传递值传递指向对象的句柄副本是否正确?我仍然没有看到传递引用或传递引用值之间的区别..
  • @brainstorm pass-by-value 正在传递值的副本。令人困惑的是,Java 中的 Object o 是一个参考。这意味着当您传递 p 时,您按值传递引用。您必须摒弃的观念是,当您看到 Object p 时,它是一个实例,因为它不在 Java 中。
【解决方案3】:

Java 总是按值传递,只是在传递对象时,传递的值是内存中的位置,因此它可以像按引用传递一样。

【讨论】:

    【解决方案4】:

    当我在 Java 中调用 swap(A,B) 等方法时,什么也没有发生,但 在 C++ 中(我想),会发生交换。

    不,它没有。 “什么都没有”也发生在 C++ 中。

    代码到 C++ 的正确翻译是:

    void swap(Object *A,Object *B) {
      Object *temp=B;
      B=A;
      A=temp;
    }
    

    (是的,不同语言的类型语法不同。即指向Foo的指针类型在C++中写为Foo *,在Java中写为Foo;这只是语言之间的句法差异.)

    【讨论】:

    • 我猜在 C++ 中,如果你通过 ref 传递,例如 swap(object &A, object &B),就会发生交换。我认为我的问题措辞非常糟糕。我会更清楚地发布一个新问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多