【问题标题】:Java Equals and Pass by value confusionJava 等于和按值传递混淆
【发布时间】:2015-09-28 07:08:30
【问题描述】:

我编写了以下程序来测试 equals 和 Java 按值传递功能(根据文档 Java 是按值传递),所以当我将对象 a 传递给方法时,我实际上是在传递堆值。如果我在方法中更改对象的引用会怎样?会发生什么?

package equalstest;

public class EqualsMethodTest {

    public static void main(String[] args) {
        EqualsMethodTest a = new EqualsMethodTest();
        EqualsMethodTest b = new EqualsMethodTest();
        System.out.println(" Comparing a and B");
        System.out.println(a == b);
        System.out.println(a.equals(b));
        EqualsMethodTest c = compare(a, b);

        System.out.println(" Comparing B and C after interchanging references");

        System.out.println(b == c);
        System.out.println(b.equals(c));

        System.out.println(" Comparing A and C after interchanging references");

        System.out.println(a == c);
        System.out.println(a.equals(c));
    }

    static EqualsMethodTest compare(EqualsMethodTest a, EqualsMethodTest b) {
        EqualsMethodTest c = a;
        a = b;
        return c;
    }
}

我得到以下输出:

比较a和B
更改前 a == b 错误
修改前 a.equals b false
交换引用后比较 B 和 C
修改后 b == c false
修改后 b.equals c false
交换引用后比较 A 和 C
修改后 a == c true
修改后 a.equals c true

  • 在方法compare 中实际发生了什么?
  • 当我创建一个新引用c 时,它是否指向a 的内存位置?
  • 当我将b 分配给a 时会发生什么?

【问题讨论】:

  • 是的,c 在调用 compare 方法后实际上与 a 具有相同的引用。当您将b 分配给a 时也没有发生任何事情,因为您是在本地范围compare 中执行的,这不会影响您的主要方法中的原始引用。另外the common SO question for this topic answers this well multiple times
  • 您可能忽略了一个事实,即对象不是在 Java 中传递或分配,而是对它们的引用(指针)。
  • compare 除了返回它的第一个参数外,什么都不做

标签: java pass-by-reference


【解决方案1】:

当我创建一个新的引用 c 时,它是否指向 a 的内存位置?

是的,因为您实际上并没有创建 c(使用 new),您只是告诉将 c 指向 a。

当我将 b 分配给 a 时会发生什么?

这里也是一样,从现在开始你的a 指向b。因此,最后你的 c 也指向 a,你将 b 指向 a

【讨论】:

    【解决方案2】:

    将 Java 称为“按值传递”虽然在技术上是正确的,但相当令人困惑。 Java 是按值传递的,但传递的值是引用。因此,您的方法中发生的情况如下:

    1. EqualsMethodTest c = a; 新变量c 的值等于参数a 的值。因此,c 现在是对与 a 相同对象的引用。
    2. a = b; 变量a 的值等于b 的值。因此ab 现在是对同一个对象的引用。
    3. return c; 返回 c 的值,它是对 a 最初指向的对象的引用。

    因为 Java 是按值传递的,所以调用 compare 的代码没有任何变化。所以如果你打电话

    `compare(a,b);`
    

    变量ab 仍然指向与以前相同的对象; compare 方法的第二行所做的更改是该方法的本地。

    【讨论】:

    • 当我做 a=b 现在 a 指向 b 并且由于 c 指向 a 不应该 c 指向 a 现在指向的位置,这只是 b。
    • @Vinay b。不,EqualsMethodTest c = a 出现在 a = b 之前。所以c 指向了原来指向的对象a。只有在之后a 的值才会改变。您必须区分引用和引用所指的对象。
    • 当 a=b 这里的 a 引用指向 b 的位置是吗?
    • 它指向b指向的同一个对象,是的。但是a = b只改变了a,而不是c,所以c仍然指向a原来指向的对象。
    【解决方案3】:

    引用可以指向新对象或任何现有对象。

    EqualsMethodTest a = new EqualsMethodTest();
       // Reference--^    ^--- new object
    

    所以当你做EqualsMethodTest c = a;时,这意味着c将指向a所指向的对象。所以基本上在这个时间点ca 两个引用都指向同一个对象。同样,a = b; 也会发生这种情况。


    传递值混淆

    Java 引用是按值传递的。

    【讨论】:

    • @Tom 对不起,没找到你。
    • @Tom,哦,我明白了。我指出,对于这个关于将变量传递给方法的问题。
    • 好吧,那么这里没什么好担心的:D。
    • @Vinayb 是否有任何答案消除了您的困惑?
    【解决方案4】:

    每次声明 EqualsMethodTest 时,实际上都是在创建一个指向 EqualsMethodTest 的指针。 因此,在您的 compare() 函数中,您正在创建一个新指针 c,它指向与 a 相同的位置。然后你告诉指针 a 指向位置 b。

    在更改之前,指针 a 指向值 a,指针 b 指向值 b。更改后,指针 c 指向值 a,指针 a 指向值 b,指针 b 指向值 b。

    【讨论】:

      猜你喜欢
      • 2012-11-20
      • 1970-01-01
      • 2019-05-10
      • 1970-01-01
      • 1970-01-01
      • 2021-11-12
      • 1970-01-01
      • 1970-01-01
      • 2016-03-15
      相关资源
      最近更新 更多