作者brianhsu (墳墓)
看板java
標題Re: [問題] 類別的方法中為何可以建立本身類別的物件?
時間Sat Nov 28 05:41:05 2009
※ 引述《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)
→ weiyucsie:剛剛查了一下 是von Neumann 11/28 06:23
※ 編輯: brianhsu 來自: 59.120.199.114 (11/28 06:35)
→ brianhsu:謝啦,已更正。:p 11/28 06:36
推 H45:可以 M 起來放精華區了.. 11/28 07:36
推 PsMonkey:從太底層的事情講太高層的現象,沒太大意義 11/28 08:05
推 H45:嘖嘖,聽說我好像是小板主吼 (偷偷收起來 XD 11/28 08:19
推 AmosYang:推 “這是值得去了解的基礎” 11/28 09:59
推 AmosYang:可惜不是每個人都有閒有機會有能力有心從基礎開始 11/28 10:05
推 aMaa:萬分感謝!! 11/28 11:24
→ TonyQ:不曉得會不會有神人來說「你們到底了不瞭解機器碼...」XD 11/28 13:54
推 ogamenewbie:然後被轉送去PLT... (大誤) 11/28 15:43
推 legnaleurc:所以 Object 的 toString 也是這個意思囉? 11/28 19:44
推 qrtt1:感謝分享 :) 11/28 22:41
推 vencees:推學長墳墓大大XD 11/29 01:05
推 chrisQQ:純推學長登出後在JAVA板的第一篇文章 XD 11/30 07:30