关于static的大字报, 还有main.

healer_kx 2008-02-29 11:38:15
1.偶为什么要写这篇文章?因为偶很无聊,很久没有写BLOG了。就到这里来扯淡。
我blog的地址是:
http://healerkx.spaces.live.com/
有200篇原创文章,随便看。

2.先说static的问题。
2.1.static的由来。
在C语言中,static主要有两个意思。
1- 函数中的静态变量。
在函数中的静态变量,只在第一次运行的时候初始化,再调用该函数,就不必再初始化了。多了不说了。而Java是没有这种变量的,但是可以有其他的方式代替。
而这个static是最纯正的static,它的生命周期是全局的,而他的作用域是函数的,其内存在程序运行之处就确定了,就是所谓的静态全局数据区。而不同于函数内的局部变量,它们的内存地址不固定,在栈空间上。
基于以上理由,称其为静态变量。
2- 文件作用域.
这个只是C的用法,不多说了。

3.C++时代的到来。
C++的static,我们知道,C++是支持面向对象编程的,那么就要有类,有实例这些概念,通常,我们把和实例的属性和方法称为成员,而不属于某一个成员,而属于整个类型的,称为类的,而在设计C++的时候,沿用了static这个关键字。而且C++程序员习惯说这个是静态成员,实际上,此静态已经转义了,几乎没有静态的意思了,其强调类属的这个概念。

4.Java的出现。
Java是沿袭了C++的语法,语义类似于SmallTalk。关键字static就是沿袭下来的。


5.误区。
因为这个所谓的静态成员(包含了成员变量和成员方法),于是一些人就开始断章取义了,说静态函数和很多静态的相关的东西的产生了联系,比如有人说静态函数所在的位置如何如何,加载的时机如何如何。这些都不是相关的问题。
我在Ruby的Self一段文字里,已经展示了,所谓的静态函数,和成员函数,在一些人所联想的地方是没有本质差别的,它们的差别在于是不是会把对象的引用作为一个隐含的参数传递给函数。

用一段伪码来表示这个关系。
假如A类有两个方法。
class A
{
void function(Arg1 a, Arg2 b);
Static void count(Arg1 a, Arg2 b);
}

那么它们的底层实现,会是这个样子的。
class Class_A_Function_Table
{
void (*p_function)(Object* p, Arg1 a, Arg2 b);
void (*p_static_count)(Object* p, Arg1 a, Arg2 b);
};
这个函数表被初始化后,那么系统就有一份函数表的实例了。
当语言的上层调用方法的时候,会把一个函数的调用者传递为第一个参数,这个调用者可能是this,可能是全局的Context。
而这个函数表,会在一开始就被初始化好,而且全局就只有一份。

6.Ruby的说法。
我觉得Ruby的说法就很好,它不再称呼这种类属的方法和成员为“静态方法”了。而是称呼为类方法。


OK,我们再来说Main方法。
7.你应该知道的几个原则。
我们考虑这样一个问题,我们在写一个类,随便一个类,然后我们需要一个功能,比如说是“从某个字符串中得到ASCII最大的字符的位置”(我承认这个例子很烂,但是你也可以想象为max(Object, Object),或者是其他的例子)。

class A
{
int indexOf(String);
}
语法凑合看,我只把最关键的语法写出来。
后来我们发现,class B也可能需要这个功能,OK,代码重用嘛,但是我们用这个功能的时候,也不能new A()啊,浪费嘛。
于是,改写成下面的模样,
class A
{
static int indexOf(String);
}
OK, 于是,到这里,你们认为这不是和main函数是static的道理是一样的嘛?No,我还有很多废话要说。

因为indexOf方法的功能,和A,和B的功能是正交的,知道什么是正交(不知道的baidu)吧?于是根据单一职责原则的理论,
有点良知和进取心的人都会把该方法移动到一个Utilities的类中,对吧?

8.Main函数就是一个普通的函数而已。
到这里,你应该明白点什么了吧?我们再继续说c/c++的main函数。
一个真正的程序员,至少应该知道一个C程序就一个main函数,作为程序的起始,不过这都是教大学生的教材说的。
如果你会写CRT的话,那么你可以让一个C程序从任何一个函数运行起来,main函数不过是在crt main上的一个对于普通开发者的开始。
可是你知道宇宙大爆炸之前就真的没有历史了嘛?
main,并非是一个真正特殊的函数,它都可以参与递归。

在Java里面,main函数是起始嘛?也许对于Java语言来说是,但是对于Java平台来说,不是。在main之前已经有很多的C函数和Java方法被调用了。

10.为什么C#只有一个Main方法?
C#和Java就像是一个弟弟,一个哥哥一样,但是Java的启动方式是java StartupClassName
于是,你可以在许多类中加入main函数,但是.Net要生成.exe文件,所以设计上倾向于只有一个Main函数,以通知.Net框架程序的入口地址是什么。
但是,.Net框架下的语言,并非所有都需要一个main的,这就说明了,main,没有什么了不起。
但是Java比较可以通过双击.jar文件,和一个.manifest文件来模拟出这种只有一个Main方法的软件行为。

我可以让一个main方法作为一个对象成员方法嘛?
可以,既然main函数不再特殊了。我就写过CRT程序,听起来很神奇,其实很简单。因为main并不特殊。
但是!! 这样做没有意义。

11.NOW!main不再特殊了,static并非静态之语义,类中的方法设计当遵循原则。
A.java,B.java,现在如果A类持有main方法,B不持有,那么我们根据面向对象的理论和单一职责原则,和其他一些习惯。
我们把A中的main,剪切到B中,当然了,不考虑import的问题,你看到了什么?
我靠,还能移动啊? 和A类没有关系啊? 那放在A类里面干鸟啊?

所以,我很明确的告诉你,main是public static的,只是语法规定,是迁就Java的语法。
所以说是迁就,是因为,真正意义上的Main方法,应该独立于任何一个类型。就像C那样的设计,可是,Java不支持全局函数啊,于是,迁就一下吧。

当然了,也不是一点关系都没有,在今天的Java里面,A里面的main通常表示A类的测试代码起始,B里面的main,也是这个意思。

main不再特殊了,static并非静态之语义,类中的方法设计当遵循原则。但是!这个main就只能放在那里,加个static。

12.public。
这个根本不用说,我除了会用public,protected是怎么回事我都不知道。


13.最近static都出来了,我也混个脸熟,眼看很多错误的理解漫山遍野的,我就只好发个帖子了。还有,经常还有很多人讨论接口的问题,我也不便在那些帖子里明确地指出谁的错误,但是我想,这种东西在理解上,要深刻,要知道接口的起源,知道接口在设计上的用处,知道接口在工程应用上的优点和缺点,知道接口如何更好的支持设计模式。但是好多人上来就说什么接口是为了什么什么,又如何设计模式纭纭,我以为,接口的出现和演化,才不是为了这些东西呢。只是在结果上达到了这样的效果而已。我很重视原因和结果这样的问题,如果在这个问题上,没有一个明确的认识,往往讲出来的东西是似是而非的。
更重要的是,是不是真正地理解了接口在面向对象上的语义了?如果只是认为可以去耦,等等。那么设计出来的对象关系是否可以保证正确的。

14.我推荐一个BLOG,希望大家可以学习一下里面的面向对象理论基础,里面有关于接口问题的解说。
http://blog.csdn.net/Slugfest




...全文
406 50 打赏 收藏 转发到动态 举报
写回复
用AI写文章
50 条回复
切换为时间正序
请发表友善的回复…
发表回复
yyb0815 2008-03-20
  • 打赏
  • 举报
回复
重头看到最后,还是有点晕,不过还是要顶一下!
dracularking 2008-03-15
  • 打赏
  • 举报
回复
呼吁大侠们成立对应的颁奖委员会给甘草颁奖 以励后进
甘草也正是这么做着的 自己却得不到奖 太不公平了
lastwords 2008-03-15
  • 打赏
  • 举报
回复
终于明白了:
我还是看不懂!
yuanjianbin 2008-03-15
  • 打赏
  • 举报
回复
UP
睿音 2008-03-14
  • 打赏
  • 举报
回复
顶上~~很少在csdn看到纯叙述技术的帖子~~赞一个。
dracularking 2008-03-14
  • 打赏
  • 举报
回复

见识了单一职责原则

行文连贯,思维敏捷且跳跃,口才卓著(忽悠功夫很好),风格且时代特征鲜明,csdn论坛的原创好文真的很少啊

赞!
paradoxchao 2008-03-14
  • 打赏
  • 举报
回复
很好,很强大
nihuajie05 2008-03-14
  • 打赏
  • 举报
回复
到这里,你应该明白点什么了吧?我们再继续说c/c++的main函数。
一个真正的程序员,至少应该知道一个C程序就一个main函数,作为程序的起始,不过这都是教大学生的教材说的。
如果你会写CRT的话,那么你可以让一个C程序从任何一个函数运行起来,main函数不过是在crt main上的一个对于普通开发者的开始。
可是你知道宇宙大爆炸之前就真的没有历史了嘛?
main,并非是一个真正特殊的函数,它都可以参与递归。
===================================================
绝对看见过...不过看见很多天了,貌似是我第一天进CSDN时看见的....呵呵
healer_kx 2008-03-14
  • 打赏
  • 举报
回复
nali?
Gump09 2008-03-11
  • 打赏
  • 举报
回复
从您的回复链到了这个帖子,又从这里链到了你得blog,随后又看了这个帖子的内容。
感觉?经验丰富的程序员-〉蓝调思想者 -〉技术专家
感觉行笔流畅带一点漫不经心。
用词准确却是不温不火。感觉很好,像读小说。
有的地方楼主的思维有点英语化。
指个小不足,标号稍微有点乱。
这种内力的楼主不多见,行文也好,可谓大家之言了。要好好学习。
nihuajie05 2008-03-11
  • 打赏
  • 举报
回复
貌似部分内容在其他地方看见哦....
甘草...你要检讨下哦~~~~~~
^_^
Squall1009 2008-03-11
  • 打赏
  • 举报
回复
晕,我一个星星都没有。。。
nihuajie05 2008-03-11
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 healer_kx 的回复:]
谢谢dd帮我UP帖子,到时候可以考虑给你分。
[/Quote]
你说的好
healer_kx 2008-03-11
  • 打赏
  • 举报
回复
你Java比我牛,所以我是比你饼子还饼子的人物。
Squall1009 2008-03-11
  • 打赏
  • 举报
回复
菜鸟不菜鸟不是重点啊,关键是这个帖子是技术帖啊-_-!
healer_kx 2008-03-11
  • 打赏
  • 举报
回复
饼子==菜鸟,比如楼上就是一个菜鸟。。。
Squall1009 2008-03-11
  • 打赏
  • 举报
回复
对了,争取在技术区把这个帖子结掉(^-^)
Squall1009 2008-03-11
  • 打赏
  • 举报
回复
我晕,我好歹也算个吧?点雨点也是吧?
  • 打赏
  • 举报
回复
谁能解释一下饼子是啥意思?看不懂...
healer_kx 2008-03-11
  • 打赏
  • 举报
回复
晕,这个除了我是饼子,还有谁?
加载更多回复(30)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧