我最近开始重构我的Java代码。它一直运行良好,直到后来,我注意到我的一些对象丢失了“正确引用”,即对象“按值传递”的情况 ,而不是“通过引用传递”。请注意,我确实理解Java始终是pass-by-value,并且通过引用传递仅通过内存地址传递进行模拟(这就是我引用这两个短语的原因)。
我的问题是:
之间有区别吗?Object o = new Object();
和
Object o = makeMeAnObjectPlease();
,其中
public Object makeMeAnObjectPlease()
{
Object c = new Object();
return c;
}
通过差异,我的意思是o
在Object o = makeMeAnObjectPlease()
引用与makeMeAnObjectPlease()
内创建的内存地址相同的内存地址后会{{1}}吗?还有其他差异吗?
答案 0 :(得分:3)
是的,它会引用同一个对象。不,没有其他差异。进一步举例:
Date d = makeMeAnObjectPlease();
System.out.println(d);
Date d2 = d;
changeMyObjectPlease(d2);
System.out.println(d);
System.out.println(d2);
Date makeMeAnObjectPlease() {
return new Date();
}
void changeMyObjectPlease(Date date) {
date.setTime(1234);
}
该代码中只有一个Date对象,尽管在不同的时间以不同的名称知道它。最后,所有名称都指向同一个对象,因此最后,当我们用两个不同的名称打印出对象时,你会看到它们实际上在内存中指示了同一个对象,它被{{ 1}}方法。运行上述内容的一个例子是:
changeMyObjectPlease()
答案 1 :(得分:2)
这两种方法之间没有功能差异。
在第一个示例中,创建了new Object
,对象的参考位置存储在Object
引用变量o
中。
在第二个示例中,c
发生了相同的过程。然后将c
(对创建对象的内存引用)的值复制到o
。如果此时c
和o
都在范围内,则o
(通过调用方法或更改字段)所做的任何突变都将反映在c
中,反之亦然。
要回答有关java中参考工作方式的问题,请考虑以下事项:
Object o,c;
o = c = new Object();
在此示例中,o
和c
都具有相同的值(对Object
的引用)并指向同一个对象。我可以将o
传递给方法,通过访问Object
中的c
来改变它指向的对象并见证更改。但是,如果我将一个新对象分配给我传入的引用(如下所示)
public class Test{
public static void main(String[] args){
Object o,c;
o = c = new Object();
assignIntoTheReferencePlease(c);
System.out.println(o == c);
}
public static void assignIntoTheReferencePlease(Object c){
c = new Object();
}
}
没有任何反应(程序会打印true
)。
为什么?
这是因为你说的是真的 - 所有的方法调用和返回都是按值传递。这意味着c
的参考值将复制到方法变量c
中。对该变量进行的任何赋值都不会影响外部作用域中的其他变量,因为它不是真正的指针。
我希望我回答你的问题。
答案 2 :(得分:1)
正如其他人所说,正如你所展示的那样,根本没有区别。唯一的区别在于它可能是什么。
例如,如果您不知道/控制定义makeMeAnObjectPlease
,它可以返回Object
的任何子类,代码仍将保留,而第一个选项将始终返回{{1} }。对于这种抽象,第二种风格通常用于Factory Pattern
。
答案 3 :(得分:1)
将在Object o = makeMeAnObjectPlease()后引用与makeMeAnObjectPlease()中创建的内存地址相同的内存地址?
我们不会谈论Java中的内存地址。它将引用相同的对象。怎么可能不是?
还有其他差异吗?
只有额外的方法调用,以及其中的任何内容。