作者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)
1F:→ weiyucsie:刚刚查了一下 是von Neumann 11/28 06:23
※ 编辑: brianhsu 来自: 59.120.199.114 (11/28 06:35)
2F:→ brianhsu:谢啦,已更正。:p 11/28 06:36
3F:推 H45:可以 M 起来放了.. 11/28 07:36
4F:推 PsMonkey:从太底层的事情讲太高层的现象,没太大意义 11/28 08:05
5F:推 H45:啧啧,听说我好像是小板主吼 (偷偷收起来 XD 11/28 08:19
7F:推 AmosYang:推 “这是值得去了解的基础” 11/28 09:59
8F:推 AmosYang:可惜不是每个人都有闲有机会有能力有心从基础开始 11/28 10:05
9F:推 aMaa:万分感谢!! 11/28 11:24
10F:→ TonyQ:不晓得会不会有神人来说「你们到底了不了解机器码...」XD 11/28 13:54
11F:推 ogamenewbie:然後被转送去PLT... (大误) 11/28 15:43
12F:推 legnaleurc:所以 Object 的 toString 也是这个意思罗? 11/28 19:44
13F:推 qrtt1:感谢分享 :) 11/28 22:41
14F:推 vencees:推学长坟墓大大XD 11/29 01:05
15F:推 chrisQQ:纯推学长登出後在JAVA板的第一篇文章 XD 11/30 07:30