Java如何分配指向对象而不是复制?

时间:2010-05-05 19:24:43

标签: java reference

在课堂上,我有:

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

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

另一种表达方式:

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

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

5 个答案:

答案 0 :(得分:16)

当变量用作方法的参数时,其内容始终被复制。 (Java只有 call-by-value。)这里要理解的重要一点是,你只能通过引用 引用对象。那么当您传递引用对象的变量时实际发生的是您将引用传递给对象(按值!)。

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

来自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 ++“引用类型”没有对应部分。

答案 1 :(得分:8)

您的上一个示例以这种方式工作,因为 int 是一个原语,它是按值复制的。在第一个示例中,“ this.bar ”将保存 bar 的引用(指针类型)的副本。因此,如果您更改原始栏(内部),更改将反映在您的班级中。试试吧。

答案 2 :(得分: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

答案 3 :(得分:1)

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

当他们通过引用/传递值来讨论这个问题时,人们会得到真正的混淆,如果你对这些术语的含义并不是很熟悉,我建议你忽略它们,并且只记得Java永远不会复制对象。 / p>

因此,java的工作方式与您希望第一个示例完全一致,这是OO Design的核心部分 - 事实上,一旦您实例化了一个对象,它就是每个人使用它的同一个对象。

处理原语和引用有点不同 - 因为它们不是对象,所以它们总是被复制 - 但实际上,java只是总是做你想做的事情而没有额外的语法或混淆选项

答案 4 :(得分:0)

为了保持成员栏的原始值,您需要实现Cloneable接口。然后,在为对象分配新值之前,您需要对其进行克隆并传递克隆值并将新值分配给克隆对象。以下是有关如何执行此操作的教程http://www.java-tips.org/java-se-tips/java.lang/how-to-implement-cloneable-interface.html