如果你喜欢住房隐喻:
一个班级就像一座房子的蓝图。使用这个蓝图,你可以建造尽可能多的房屋,你喜欢。
>你建立的每个房子(或实例化,在OO lingo)是一个对象,也称为一个实例。
当然,每个房子也有一个地址。如果你想告诉某人房子在哪里,你给他们一张带有地址的卡片。该卡是对象的参考。
>如果你想访问房子,你可以看看卡上写的地址。这被称为解引用。
您可以尽可能多地复制该参考,但只有一个房子 – 您只需复制具有地址的卡,而不是房屋本身。 Java方法总是传递值,但该值可以是对象的引用。所以,如果我有:
Foo myFoo = new Foo(); // 1
callBar(myFoo); // 2
myFoo.doSomething() // 4
void callBar(Foo foo) {
foo = new Foo(); // 3
}
然后让我们看看发生了什么。
>有一些事情发生在第1行。new Foo()告诉JVM使用Foo蓝图构建一个新房子。 JVM这样做,并返回对房子的引用。然后,将此引用复制到myFoo。这基本上就像要求承包商建一个房子。他呢,然后告诉你房子的地址;你写下这个地址。
>在第2行中,您将此地址转给另一种方法callBar。接下来让我们跳到那个方法。
>在这里,我们有一个参考Foo foo。 Java是pass-by-value,所以callBar中的foo是myFoo引用的副本。想想它就像给CallBar自己的卡一样,房子的地址就可以了。 callBar用这张卡做什么?它要求建一座新房子,然后使用你给它的卡片写新房子的地址。请注意,callBar现在不能到达第一个房屋(我们在第1行建立的房子),但是房子没有改变,因为一个卡片曾经有它的地址,现在有一个其他房子的地址。
>回到第一个方法,我们取消引用myFoo来调用它的方法(doSomething())。这就像看着卡片,去那个地址在卡上的房子,然后在那个房子里做某事。请注意,我们的myFoo地址卡与CallBar方法保持一致 – 请记住,我们给了callBar一份我们的参考。
整个序列将是:
请求JVM建房子。它是,并给我们的地址。我们将此地址复制到名为myFoo的卡。>我们调用callBar。在我们做之前,我们将在myfoo上写的地址复制到一个新的卡片上,我们给callBar。它称该卡为foo。> callBar询问JVM为另一个房子。它创建它,并返回新房子的地址。 callBar将此地址复制到我们给予的卡上。回到第一种方法,我们来看看我们原来的,不变的卡;去我们的卡上的地址;并在那里做某事。