你好,阿米戈!我想向你介绍变量的内部结构。如你所知,每个变量都与存储其值的内存区域关联。”
“是的。你上次告诉过我。”
“太好了。你能记住真是不错。那我继续。”
“所有复合类型都由较简单的类型组成。而较简单的类型又由更简单的类型组成。直到最后,我们得到无法进一步简化的原始类型。因此称之为 – 原始类型。例如,int 是原始类型,但 String 是将数据以字符表方式存储的复合类型(其中每个字符是原始类型 char)。”
“非常有趣。继续。”
“复合类型是通过对简单类型进行分组而形成的。我们将这种类型称为类。当我们在程序中定义一个新类时,我们声明一个新的复合数据类型。其数据要么是其他复合类型,要么是原始类型。”
Java 语言代码 | 说明 |
---|---|
|
声明一个新的复合类型 – Person 。其数据存储在 String (复合类型)变量 name 和int (原始类型) 变量 age 中 |
|
声明一个新的复合类型 – Rectangle 。它由四个 int (原始类型)变量组成。 |
|
声明一个新的复合类型 – Cat 。它具有以下变量:— owner ,复合类型 Person — territory ,复合类型 Rectangle — age ,原始类型 int — name ,复合类型 String |
“到目前为止,一切都很清楚,但看起来可能有点奇怪。”
“大(复合)类型包含许多小(原始)类型。这正是这些类型的对象占用大量内存的原因 - 超出原始类型的变量。有时甚至更多。使用此类变量执行赋值操作通常会花很长时间,并且需要复制大部分内存。这就是复合类型的变量不存储对象本身,而只存储对象引用(即对象的四字节地址)的原因。这样做足以处理此类对象中的数据。Java 机器处理所有相关的复杂性。”
“我完全不明白。”
“我们以前说过,一个变量就像一个盒子。如果你想在盒子中存储数字 13,你可以在一张纸上写下 13 并将其放入盒子中。”
“但是想象一下,你需要在盒子(变量)中存储更大的东西。例如,狗、汽车或你的邻居。不要尝试将不可推动的物体推入盒子,你可以做得更轻松:用狗的照片代替实际的狗,用车牌代替真实的汽车,或者用邻居的电话号码代替邻居。”
“我们拿一张纸,写下邻居的电话号码。这就像对象的引用。如果我们复制写有邻居电话号码的纸并将其放入几个盒子,则现在有更多对你邻居的引用。但是,像以前一样,你仍然只有一个邻居。这样说没错,对吧?”
“以这种方式存储数据的一个重要特性就是你可以拥有对一个对象的多个引用”
“太有趣了!我基本上明白了。请再告诉我一次 – 如果将一个复合类型的变量赋给相同复合类型的另一个变量会发生什么?”
“那样的话,这两个变量将存储相同的地址。这意味着,如果更改一个变量所引用的对象的数据,则会更改其他变量所引用的数据。两个变量引用同一个对象。当然,可能还有许多其他变量也存储该对象的引用。”
“如果复合(引用/类)类型的变量不包含对某个对象的引用,它们将做什么?有这种可能吗?”
“是的,阿米戈。你已经超前提问了。这是可能的。如果引用(复合)类型的变量未存储某个对象的引用,它将存储所谓的‘null 引用’。大致说来,这意味着它引用地址为 0 的对象。但是,Java 机器从不使用此地址创建对象,因此它始终知道,如果引用变量包含 0,则它不指向任何对象。”
Java 语言代码 | 说明 |
---|---|
|
等效语句。 |
|
我们创建值为 null 的 person 变量。 我们将新创建的 Person 对象的地址赋给该变量。 我们将 null 赋给该变量。 |
|
我们创建 Cat 对象,并将其地址存储在变量 cat 中;cat.owner 等于 null。 我们将 cat.owner 设置为等于新创建的 Person 对象的地址。 cat.owner.name 仍然等于 null。 我们将 cat.owner.name 设置为等于“上帝” |
“我的理解正确吗?变量分为两种类型:原始类型和引用类型。原始类型直接存储值,而引用类型存储对象的引用。原始类型包括 int、char、boolean 和许多其他类型。引用类型包括其他所有类型。我们使用类来创建它们。”
“你说的完全正确,小伙子。”
“嗯,你说你已经完全明白了。这里有一些任务,可以帮助你增强对知识的理解。”
GO TO FULL VERSION