【问题标题】:How is Java parameter reference and original reference (not object) the same? [duplicate]Java参数引用和原始引用(不是对象)如何相同? [复制]
【发布时间】:2017-11-12 15:53:09
【问题描述】:

所以我们知道Java 使用按值传递,即它将引用的副本传递给方法。 我想知道为什么会这样,当我用原始参考(我的例子中的string)测试参数参考(我的例子中的param)时说它们是一样的?

下面的代码不应该返回false,即引用不一样,因为复制引用(即新引用)是按值传递的吗?

public class Interesting {

  private String string;

  public Interesting(final String interestig) {
    super();
    string = interestig; // original reference is tested against copy reference and it says they are the same
  }

  public boolean isItTheSame(final String param) {
    return param == string;
  }

  public static void main(final String args[]) {
    Interesting obj = new Interesting("String");
    System.out.println(obj.isItTheSame(obj.string)); //copy of reference is created here
  }
}

【问题讨论】:

  • 我没有看到任何创建副本的部分?您认为哪个部分创建了副本?
  • OCA 指南是这样写的:“被调用的方法然后获取它自己的引用变量副本,以按照自己的意愿使用它。”章节将变量传递给方法 - OCA 目标 6.8
  • @AndrewLi 你错了。 Atti 正确地引用了它。引用被复制。你认为那是说对象被复制了,但这不是这句话所说的。这就像复制一个原始值。
  • 我想知道“Is Java "pass-by-reference" or "pass-by-value"?”是否仍然是一个合适的骗子,因为它很好地涵盖了变量和引用及其行为。

标签: java parameter-passing pass-by-reference pass-by-value


【解决方案1】:

引用变量是一个引用。它包含一个特定的位模式,用于标识对象的位置。这在计算机科学中称为指针Per the JLS,“引用值(通常只是 references)是指向这些对象的指针”。指针值,就像原语一样,只是通过它们的位模式传递给方法。相同的模式意味着它们指向相同的对象。这就是== 检查两个指针​​是否指向同一个对象。这就是你得到这个结果的原因。

【讨论】:

    【解决方案2】:

    不,因为 == 也会比较引用的;如果两个引用都指向同一个对象,则返回 true。

    【讨论】:

    • 但是它们不是同一个引用......如果我们重新分配参数引用,原始对象不会受到影响。
    • @Atti 这是正确的,但你不要在这里重新分配任何东西。
    • @Michael:但我认为如果我们有两个不同的引用并 == 测试引用,那将是错误的......我在这里错过了什么?谢谢!
    • @Atti:对同一个对象的两个不同引用包含相同的值,就像两个不同的 int 变量可以包含相同的值一样,并且在这两种情况下,这些值都被认为是相等的。甚至比较身份而不是平等的参考有什么意义?你需要它做什么?在许多情况下,两个引用指向同一个对象是一个有用的信息。
    【解决方案3】:

    引用是它自己的值。字符串"String" 位于特定的内存位置,例如 0x01ab64e。因此,引用该字符串的任何引用的值都是 0x01ab64e。不能引用具有不同值的那个字符串,因为那样它就不会引用那个字符串,而是引用一个不同的字符串。

    “按值传递”是指按值传递引用,而不是按值传递实际引用的对象(字符串)。因此,传递了完全相同的引用。这就是为什么它是一样的。

    要验证引用是否按值传递(并且该值是副本),请尝试以下操作:

    String s = null;
    foo( s );
    assert s == null;
    
    void foo( String s )
    {
        s = "not null";
    }
    

    断言没有失败,这意味着调用者持有的引用s没有被改变。这意味着引用 s 是按值传递的(始终是副本),因此 foo() 只更改了它自己的引用副本的值,而调用者的副本不受影响。

    【讨论】:

    • 但是参数s(在foo 方法中)与第一行中的String s 不是不同的引用吗?
    • @Atti 你真的应该开始区分variablesreferences。两个不同的变量(如第一行中的s 和方法参数中的s)仍然可以对堆中的同一个String 对象具有相同的引用。然后,当您在 foo 中执行 s = "not null" 时,它们会有所不同。
    • @Mike:我明白了。谢谢你的解释!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-12
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    • 2012-08-13
    • 2014-07-14
    相关资源
    最近更新 更多