Re: [問題] 類別的方法中為何可以建立本身類別的物件?
※ 引述《aMaa (aMa)》之銘言:
: 今天我有實作測試一下,
: 不管是public static void main還是一般method都可以new本身類別的物件
:
: 只是不知道原理為何?
【離題】
說實話,這個討論串讓我想到之前在自己的部落格上寫到的這一篇
雜記裡關於程式語言學習的部份,有問到到底在學習程式式語言的
時候,要從何處入手【註 0】。
【註 0】 http://bone.twbbs.org.tw/blog/archives/1173
這一串討論看下來,看來看去,只有一個想法:會有這種疑問,根
本就是因為不了解整個 von Neumann架構/程式語言/編譯器/機
器語言/虛擬機器之間的關連所造成的嘛……
以下,可能很長,可能很多看似無關緊要的東西(就算你不懂,你
的程式還是可以動),可是我自己認為這是值得去了解的基礎,如
果你真的用心了解下面所講的東西,基本上就不會再出現類似的疑
惑了。
【回題】
其實原 PO 的問題本質上和另一個問題一樣:為什麼像是下面的遞
迴程式裡,第 6 行的時候,明明 sum 還明有定義完,卻可以呼
叫自己呢?
// 用遞迴計算 1 + 2 + ... + n
1 int sum (int n) {
2 if (n == 1) {
3 return 1;
4 }
5
6 return n + sum(n-1);
7 }
為什麼下面的程式裡,Node 明明還沒定義完,裡頭卻又出現另一
Node 呢?
1 class Node {
2 private Node next;
3 }
我真的很想大叫:不要鬧了!大家到底知不知道 Java 程式語言/
Bytecode / Virtual Machine / von Neumann 電腦架構 / 原生可
執行檔/器與語之間的關係,到底知不知道一個 Java 程式是怎麼
執行的啊?!
請問你自己一個問題:Java 程式執行的時候,是執行你寫的原始
碼嗎?
(答:不是,實際上執行的是 bytecode,也就是 javac 翻譯出來
的 .class 檔)
請問你自己第二個問題:你在執行你的 Java 程式 (Bytecode) 的
時候,你知道 Bytecode 到底是什麼東西,做什麼用的嗎?
(答:可以將 Bytecode 視為一套虛擬的『類機器語言』,將其交
由 Virtual Machine 解譯後,可以產生電腦 CPU 真正能夠理解
的機器語言指令)
請問你自己第三個問題:你知道什麼叫 von Neumann 架構嗎?你知
道一個『原生電腦程式』是如何在 von Neumann 架構上執行的嗎?
(答:如果不知道,請參閱『小人電腦』【註 1】,裡面是簡化版
的說明,但基本上目前的所有電腦都不脫離這個架構。)
【註 1】http://programming.im.ncnu.edu.tw/Chapter2.htm
如果你看完了上面的小人電腦,請你問你自己第四個問題:你在小
人電腦裡,有看到『資料結構』、『函數』、『物件』、『類別』
這種東西嗎?
(答:沒有,只有記憶體/指令/暫存器/Program Counter ,而
且記憶體位置好像也都知能存數字【註2】)
(謎之音:那我的函數、物件、資料夾構在哪裡?提示:我們還有
可執行檔以及 Bytecode 這兩個東西沒講到。)
【註 2】嚴格來說這並不正確
請再問你自己第五個問題:你知道我們剛剛『定義』出來的計算總
合的函式,如果翻譯成小人電腦的機器語言,用上述網頁中的機器
語言表示出來會長什麼樣子嗎?
(答:你會看到 sum(n-1) 被翻成一個 CALL 指令,其參數 XX 的
部份會是此函數的開頭,而 return 會被翻成 RETURN ,如果你不
知道這是什麼意思,請把小人電腦再認真看一次,並注意最後一個
函數呼叫的例子)
以上,是回答為什麼函數可以呼叫自己。
接下來,請再問你自己:記憶體 / 指標 / 參考 / 物件之間,究
竟是什麼關係,你知道第二個 Node 的 Java 程式碼,被載入到記
憶體後,到底長什麼模樣嗎?
(答:指標和參考本質上都是相同的,都是『記憶體位置』)
這不就很明顯了嗎?private Node next,說的是『next 是一個記
憶體位置,而且這個記憶體位置應該要指到一個長得像 Node 的物
件』。
但 next 真的必需指到 Node 物件嗎?(提示:多型/強制轉型/執
行期錯誤)他不過就是個數字,來表示記憶體位置,誰管他指到什
麼地方啊!
所以說,這有什麼好訝異的?不過就是『在 Node 的這個物件裡,
有一個欄位是一個數字,他指到某一個記憶體的位置,而這個記憶
體位址上的內容,應該要是另一個Node 物件(但不必然是)。』
這很直覺,很正常啊!
最後,回到原 PO 的問題,如果再把原 PO 的問題更簡化,可以問
另一個問題,那就是以下的 Java 程式碼是否合法,如果它合法的
話,執行這段 Java 程式碼裡的 test() 到底會發生什麼事,記憶
體裡產生了哪些變化?
class Hello
{
public void test ()
{
Hello hello = new Hello();
}
}
public class Test
{
public static void main (String [] args)
{
Hello hello = new Hello ();
hello.test ();
}
}
接下來,你要問你自己,Java 裡 new 出來的物件,到底在是住在
記憶體的哪裡?而指到各物件的參考又活在哪裡?是在 Stack 還
是在 Heap ?指標裡存的又是什麼?
再來, hello.test() 這一行會翻譯成什麼小人電腦的組合語言?
(提示:Method call 和 function call 本質上是一樣的東西)
如果,你能回答出以上的問題,基本上就不會有『為什麼函數沒有
定義完還可以呼叫自己,為什麼物件可以 new 自己,為什麼明明
就還沒定義完,Node 裡卻可以有 Node』 的這種疑問了。
謎之音:所以說,這篇『爪哇學校的危害』【註 3】還是有他的道
理在的啊!
【註 3】英文版:http://0rz.tw/f00Zg
中文版:http://0rz.tw/g3JZo
--
~ 白馬帶著她一步步地回到中原。白馬已經老了,只能慢慢地走,
'v' Brian Hsu 但終是能回到中原的。江南有楊柳、桃花,有燕子、金魚……
// \\ ( 墳 墓 )
/( )\ 但這個美麗的姑娘就像古高昌國人那樣固執。 【白馬嘯西風】
^`~'^
http://bone.twbbs.org.tw/blog 『那都是很好很好的,可我偏不喜歡。』
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 59.120.199.114
※ 編輯: brianhsu 來自: 59.120.199.114 (11/28 05:46)
→
11/28 06:23, , 1F
11/28 06:23, 1F
※ 編輯: brianhsu 來自: 59.120.199.114 (11/28 06:35)
→
11/28 06:36, , 2F
11/28 06:36, 2F
推
11/28 07:36, , 3F
11/28 07:36, 3F
推
11/28 08:05, , 4F
11/28 08:05, 4F
推
11/28 08:19, , 5F
11/28 08:19, 5F
推
11/28 09:52, , 6F
11/28 09:52, 6F
推
11/28 09:59, , 7F
11/28 09:59, 7F
推
11/28 10:05, , 8F
11/28 10:05, 8F
推
11/28 11:24, , 9F
11/28 11:24, 9F
→
11/28 13:54, , 10F
11/28 13:54, 10F
推
11/28 15:43, , 11F
11/28 15:43, 11F
推
11/28 19:44, , 12F
11/28 19:44, 12F
推
11/28 22:41, , 13F
11/28 22:41, 13F
推
11/29 01:05, , 14F
11/29 01:05, 14F
推
11/30 07:30, , 15F
11/30 07:30, 15F
討論串 (同標題文章)
java 近期熱門文章
PTT數位生活區 即時熱門文章