在课堂上,我有:
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?
答案 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。