作者brianhsu (坟墓)
看板java
标题Re: 搞懂变数、物件、参考。(Re: new 语法 …
时间Fri Jan 1 20:55:28 2010
=======================================================
1 void func ()
2 {
3 int x = 10; // Type 1
4 Object object; // Type 2
6 int [] array; // Type 3
7 Object [] array2 // Type 4
9
10 object = new Object ();
11 array = new int[2]
12 array2 = new Object[2]
13 }
=======================================================
继续,照上面的那四个口诀,进入这个函式之後的每一步,记忆体长
什麽样子呢?其中问号代表不知道实际的值是什麽,每一次执行都有
可能不一样(危险的事情,惊)!
另外,下面所有的图你都不会看到 CODE 的部份,因为『CODE 永远
不会变,会变的只有 DATA!』
1. inx x = 10;
我是 Stack 右边都是 Heap
+-----------+
我叫 x | 10 |
+-----------+
2. Object object;
我是 Stack 右边都是 Heap
+-----------+
我叫 object | ??? |
+-----------+
我叫 x | 10 |
+-----------+
3. int [] array;
我是 Stack 右边都是 Heap
+-----------+
我叫 array | ??? |
+-----------+
我叫 object | ??? |
+-----------+
我叫 x | 10 |
+-----------+
4. Object [] array2;
我是 Stack 右边都是 Heap
+-----------+
我叫 array2 | ??? |
+-----------+
我叫 array | ??? |
+-----------+
我叫 object | ??? |
+-----------+
我叫 x | 10 |
+-----------+
以上,是程式执行到第 7 行时记忆体里的状况,我们的人脑 CPU 总
算把变数给宣告和初始化完了(泪)!
接着来看 new 这个关键字吧,这个关键字其实说起来很简单的。
======================================================================
程式码 口诀
new Object (); 请在 Heap 里生一个 Object 物件给我,并且返回这个物
件的『
记忆体地址』
new int [2]; 请在 Heap 里生一个长度为 2 的阵列物件给我,其中每
个元素存的应该是个整数,并且返回这个阵列物件的『
记
忆体地址』
new Object[2]; 请在 Heap 里生一个长度为 2 的阵列物件给我,其中每
个元素存的是记忆体地址,而这些记忆体地址应该要指到
Heap 里类别为 Object 的物件。最後,请返回这个阵列
物件的记忆体地址。
======================================================================
所以,以下的程式码就很简单地可以了解了吧!?
注意!以下的记忆体地址只是概念,实际上执行时由 VM 决定到底在哪,每一次
执行都有可能在不同的位值。
1. object = new Object (); // 请在 Heap 里生一个 Object 物件给我,并且把
// 返回的记忆体地址塞到 Stack 上名为 object
// 的东西里。
我是 Stack 右边都是 Heap
+-----------+
我叫 array2 | ??? |
+-----------+
我叫 array | ??? |
+-----------+ +-----------------+
我叫 object | 0x1234 | -----------> | Object 物件 | 我活在 0x1234
+-----------+ +-----------------+
我叫 x | 10 |
+-----------+
2. array = new int [2];
// 请在 Heap 里生一个长度为 2 的阵列物件给我,其中每个元素存的
// 应该是个整数。最後把这个阵列物件的记忆体地址塞给 Stack 上叫
// array 的东西里。
我是 Stack 右边都是 Heap
+-----------+ +--------+--------+
我叫 array2 | ??? | +->| 整数 | 整数 | 我活在 0x3456
+-----------+ | +--------+--------+
我叫 array | 0x3456 | ----------+
+-----------+ +-----------------+
我叫 object | 0x1234 | -----------> | Object 物件 | 我活在 0x1234
+-----------+ +-----------------+
我叫 x | 10 |
+-----------+
3. array2 = new Object[2];
// 请在 Heap 里生一个长度为 2 的阵列物件给我,其中每个元素存的
// 应该是个整数。最後把这个阵列物件的记忆体地址塞给 Stack 上叫
// array 的东西里。
我是 Stack 右边都是 Heap
+--------+--------+
+----> | ??? | ??? | 我住在 0xA000,但
| +--------+--------+ 我没有名字。
|
+-----------+ | +--------+--------+
我叫 array2 | 0xA000 | ------+ +->| 整数 | 整数 | 我住在 0x3456,但
+-----------+ | +--------+--------+ 我没有名字。
我叫 array | 0x3456 | ----------+
+-----------+ +-----------------+
我叫 object | 0x1234 | -----------> | Object 物件 | 我住在 0x1234,但
+-----------+ +-----------------+ 我没有名字。
我叫 x | 10 |
+-----------+
到这边,上面这个函式结束前,记忆体内的状况长得就是这样。
接下来换你罗,请问文章一开头的这个程式,执行到第 10 行为止,记忆体
应该长什麽样子呢?
===== ClassExample.java =====
1 public class ClassExample
2 {
3 int x = 3;
4
5 public static void main (String [] args)
6 {
7 int stackVar = 10;
8
9 ClassExample ex = new ClassExample ();
10 System.println ("ex.x = " + ex.x);
11
12 return;
13 }
14 }
============================
提示,你的 Heap 里的 ClassExample 物件会长得像下面一样。
我是 Stack 右边都是 Heap
+------------+ x
| | +-----+--------------+
| | | 3 | ........... | 假设我活在 0x1234
^^^^^^^^^^^^^^ +-----+--------------+
^^^^^^^^^^^^^^
| |
+------------+
如果你能正确画出来左边 Stack 的图,那基本上你对於 Java 里面的
变数/参考/物件的观念应该没有太大的问题。
最後,提醒一下,所谓『内容是记忆体位址的变数』在 Java 里就叫做
reference(参考),在其他程式语言里有时会叫做 pointer(指标)。
--
~
白马带着她一步步地回到中原。白马已经老了,只能慢慢地走,
'v'
Brian Hsu 但终是能回到中原的。江南有杨柳、桃花,有燕子、金鱼……
// \\
( 坟 墓 )
/( )\
但这个美丽的姑娘就像古高昌国人那样固执。 【白马啸西风】
^`~'^
http://bone.twbbs.org.tw/blog 『那都是很好很好的,可我偏不喜欢。』
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 59.120.199.114
1F:推 starericc:推 01/01 21:00
2F:推 dendrobium:应该把某位置再指到对应的物件上,不过可能画不下XD 01/01 21:07
※ 编辑: brianhsu 来自: 59.120.199.114 (01/01 21:11)
※ 编辑: brianhsu 来自: 59.120.199.114 (01/01 21:26)
3F:推 sbrhsieh:这样子的观念讲的很清楚很好。为了完整性可能要在图上 01/02 16:33
4F:→ sbrhsieh:加注 stack 中的值与 heap 中物件的位置不见得是直接的。 01/02 16:35
5F:→ sbrhsieh:或是使用这样子的线条 -----//----->(有比较好吗?) 01/02 16:38
6F:推 ashin10:推 01/02 23:16
7F:推 papayamilk:推 04/20 20:48