【问题标题】:How can Java assignment be made to point to an object instead of making a copy?如何进行 Java 赋值以指向对象而不是复制?
【发布时间】:2010-05-05 19:24:43
【问题描述】:

在课堂上,我有:

private Foo bar;
public Constructor(Foo bar)
{
    this.bar = bar;
}

除了从参数中提供的对象创建 bar 的副本之外,是否可以在构造函数中包含指向 bar 的指针,以便更改原始 bar 会更改此对象中的字段?

另一种说法:

int x = 7;
int y = x;
x = 9;
System.out.print(y); //Prints 7.

是否可以设置为打印 y 打印 9 而不是 7?

【问题讨论】:

    标签: java reference


    【解决方案1】:

    当变量用作方法的参数时,它的内容总是被复制。 (Java 有only call-by-value。)这里要理解的重要一点是,您可以only 通过引用来引用对象。因此,当您传递引用对象的变量时,实际发生的情况是您将引用传递给对象(按值!)。

    有人可能会告诉你“基元是通过值传递的”和“非基元是通过引用传递的”,但这仅仅是因为变量永远不能包含对象,只能包含对对象的引用。当有人理解这一点时,他会同意即使是引用对象的变量也是按值传递的。

    来自Is Java "pass-by-reference" or "pass-by-value"?

    Java 总是按值传递。很难理解 Java 将对象作为按值传递的引用传递。

    来自http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html

    Java 确实通过引用来操作对象,并且所有对象变量都是引用。但是,Java 不会通过引用传递方法参数。它按值传递它们。

    在 Java 中,原语的 C++“引用类型”没有对应的部分。

    【讨论】:

    • 第一句话是对的,但可能会误导许多使用 Java 的人认为“变量是对象”(实际上变量是对对象或原语的引用) .初学者必须首先了解的是,对象本身在作为参数传递时永远不会被复制。
    【解决方案2】:

    你的最后一个例子是这样工作的,因为 int 是一个原语,它是按值复制的。在第一个示例中,“this.bar”将保存对 bar 的引用(某种指针)的副本。因此,如果您更改原始栏(内部),更改将反映在您的课程中。试试看。

    【讨论】:

    • “int 是一个原语,它是按值复制的”可能会有点混乱。引用也是按值复制的。
    • 是的。但海报是从物体的角度思考的。首先要了解对象(与 C++ 不同)永远不会按值复制,这​​一点很重要。
    【解决方案3】:

    要获得该行为,您可以修改对象的成员:

    public class Number{
      int value;
      Number(int value){
        this.value = value;
      }
      public String toString() {
        return "" + value;
      }
    }
    

    你可以这样做:

    Number x = new Number(7);
    Number y = x;
    x.value = 9;
    System.out.println(y);//prints 9
    

    【讨论】:

      【解决方案4】:

      Java 从不复制对象。最容易想到的是,对于每个“新”,您将拥有一个对象实例——永远不会更多。

      人们在讨论引用传递/值传递时会感到非常困惑,如果您对这些术语的含义不是很熟悉,我建议您忽略它们并记住 Java 从不复制对象。

      所以 java 的工作方式与您希望第一个示例的工作方式完全相同,这是 OO 设计的核心部分——一旦您实例化了一个对象,它对每个使用它的人来说都是同一个对象。

      处理原语和引用有点不同——因为它们不是对象,所以它们总是被复制——但最终的结果是,java 几乎总是在做你想做的事情,而不需要额外的语法或令人困惑的选项.

      【讨论】:

      • 嗯,我正在读这篇文章,我认为内存对象模型并不难。我在这里,因为 Java 没有做我打算做的事情,如果你认为这完全是我无法编写 Java,我会同意你的看法。但事实是,Java 并不总是只做你想做的事,这种说法是错误的和误导性的。深入了解语言模型是一项非常宝贵的知识,您不应该用 Java 或任何其他语言的任何超级特性来诋毁该知识。
      • @PedroRodrigues 好的,如果您了解内存模型和指针,我可以为您提供更多帮助-这是理解它的最简单方法:1)您传递给方法的东西不能由被调用代码更改 2) 在内部函数的情况下,值不会改变。 3) 在对象的情况下,对象指针不会改变。如果您打算做的是更改传递的指针(更改原始指针),那么只需使用 java 就忘记这一点,它会为代码增加很多复杂性,而没有太大的好处。否则,我很想听听你想在 java 不同的地方做什么。
      【解决方案5】:

      为了保持会员栏的原始值,您需要实现Cloneable接口。然后在为对象分配新值之前,您需要对其进行克隆并传递克隆值并将新值分配给克隆对象。这是一个关于如何做到这一点的教程http://www.java-tips.org/java-se-tips/java.lang/how-to-implement-cloneable-interface.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-08-17
        • 1970-01-01
        • 2023-03-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多