2

我最近开始重构我的 Java 代码。一切都运行良好,直到后来,我注意到我的一些对象丢失了“正确引用”,即对象是“按值传递”,而不是“按引用传递”。请注意,我确实理解 Java 始终是按值传递的,而按引用传递只能通过内存地址传递来模拟(这就是我引用这两个短语的原因)。

我的问题是:两者之间有区别吗

Object o = new Object();

Object o = makeMeAnObjectPlease();

在哪里

public Object makeMeAnObjectPlease()
{
    Object c = new Object();
    return c;
}

不同的是,我的意思是oObject o = makeMeAnObjectPlease()与内部创建的内存地址相同的内存地址makeMeAnObjectPlease()吗?还有更多的区别吗?

4

4 回答 4

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 对象,尽管它在不同的时间有不同的名称。最后,所有的名字都指向同一个对象,所以最后,当我们用两个不同的名字将对象打印出来时,你会发现它们实际上表示内存中的同一个对象,并且被changeMyObjectPlease()方法修改了。运行上述示例是:

Thu Jan 31 19:29:29 CST 2013
Wed Dec 31 18:00:01 CST 1969
Wed Dec 31 18:00:01 CST 1969
于 2013-02-01T01:24:30.597 回答
2

这两种方法在功能上没有区别。

在第一个示例中,new Object创建了 a 并将对象的引用位置存储在Object引用变量o中。

在第二个例子中,同样的过程发生在c. 然后将c(对创建对象的内存引用)的值复制到o. 如果此时两者co都在范围内,则对(通过调用方法或更改字段)所做的任何o更改都将反映在c其中,反之亦然。

要回答有关参考如何在 java 中工作的问题,请考虑以下事项:

Object o,c;
o = c = new Object();

在此示例中,两者oc具有相同的值(对 an 的引用Object)并指向同一个对象。我可以传入o一个方法,改变它指向的对象,并通过访问Objectfrom来见证变化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中。对该变量所做的任何分配都不会影响外部范围内的其他变量,因为它不是真正的指针。

我希望我回答了你的问题。

于 2013-02-01T01:41:42.457 回答
1

正如其他人所说,正如你所展示的那样,根本没有区别。唯一的区别在于可能是什么。

例如,如果您不知道/控制定义makeMeAnObjectPlease,它可以返回 的任何子类Object,并且代码仍将保留,而第一个选项将始终返回Object。正是由于这种抽象,第二种风格通常用于Factory Pattern.

于 2013-02-01T01:26:33.593 回答
1

Object o = makeMeAnObjectPlease() 之后的 o 是否会引用与在 makeMeAnObjectPlease() 中创建的内存地址相同的内存地址?

我们不谈论 Java 中的内存地址。它将引用同一个对象。怎么可能没有?

还有更多的区别吗?

只有额外的方法调用,以及其中的任何内容。

于 2013-02-01T01:27:36.243 回答