C/C++ VS Java
若不是因为工作需要等外在因素的影响,而仅仅出于个人喜好的话,选择Java而放弃C++的,
就都是那类没有意志、不重视基础、脑子不够用、思维和编程水平也极低下的编程民工(码农)。
java开源又专利,当了婊子还想立牌坊
C/C++ VS Java
http://www.chinaitpower.com/A/2001-10-20/2279.html
- 真正的程序员今天应该对JAVA嗤之以鼻。
- 真正的程序员是C++程序员。
- 真正的学者是古PASCAL程序员(注意不要和今天的PASCAL搭上关系,另文备述)
---- 包容能力 ----
象C++/C这样的能够适应多种方面需求的编程语言,时至今日,仅此一家。
从目前看来,乃至可预见的将来,JAVA不可能做到如此的适应能力。
---- 灵活性 ----
模板
C++的模板,是整个C++发展史上的第二转折点(提出C++第一了)。这为你提供了广阔的发展空间,更加有利与代码的复用。从这个角度来看JAVA的那些可怜的多态,继承,其实仅仅是照搬C++刚发布时的早期成果,有什么好值得骄傲的?
自然,模板比类还要难于理解,以至于看懂STL源码都成了不少初学者认为理所当然的想要跨过的龙门了。
硬件能力
不必太深层的硬件操纵能力,仅仅是打开MODEM,设置一个自动应答的铃声次数,JAVA程序员将会抓耳挠腮不知如何是好。所以,片面的看待JAVA的简单,把简易当作是容易,是大错特错的。
---- 基本语法的疑问 ----
---- 类体系的疑问 ----
JAVA引用了Smalltalk的体系,整个类树都是从Object元对象生长出来的;
C++则与此不同,你可以拥有任意多个基本元对象,并据此构造出n颗类树出来。
正确的看法是两者各有利弊,无所谓谁是最优的。但是JAVA支持者则强调同源而出的种种好处,引发的论战后果是C++支持者们又论述多颗树的好处。
我以为,这就是JAVA的好处了:引发这些讨论,是可以让理论被深入化的。
---- 虚构造的疑问 ----
JAVA似乎发展出了多态构造函数的语法。如果确实如此,我需要认真想想尚在构造期间的对象是否应该多态。
为了书写这个小标题,我进一步查学了有关的内容。原来,JAVA还是照搬了旧有的规矩,禁止构造函数的多态。取而代之的,利用RTTI机制,JAVA能实现一种“虚构造”函数机制,基本上是利用类中的main()入口点来完成的。
谈及这里,我顺便以为,一个类中两个孑然不同的入口点(常规构造和main),实在是JAVA的败笔。即便是为了实现特别算法,也不应该推广出类中的main入口点。这让人无所适从。
---- 类查找的疑问 ----
JAVA的类名查找算法是让训练有素的智者也为之奈何的选择。不必提及初学者的“java.lang.NoClassDefFoundError:”问题了。即使是老手,也会被莫名其妙的类名隐藏弄到不知所措,而且难于定位故障之所在。
此外,SUN推荐你打包自己的package使用倒序域名的手段,理由是域名是官方唯一的。可惜在今天域名交换和纠纷频繁的情况下,这不见得是一种好选择。
由于域名的混乱性,中国人也许又该问一句,我使用中文域名的话,我的package又该怎办?可以使用"中国.王中华.util.Vector"这样的名字么?这一点,即使C++也被VB比了下去。VB(VBA)可以使用全中文的变量名、函数名等等标识符命名法则!
---- 继承嵌套类的疑问 ----
先看这个实例:
class Outer {
class Inner{}
}
class ChildOfInner extends Outer.Inner {
ChildOfInner(){(new Outer()).super();}
}
你有什么感觉?我是真的难以理解,这种语法破坏了嵌套类的基本规则:为了隐藏一个局部特性的对象,我们将一个类声明为Outer类的内里。
作为嵌套类,正是因为除了Outer之外,不属于其他任何人,所以才会被隐藏在Outer之中。反之,依照上述的例子,ChildOfInner从Outer.Inner派生出来,意欲何为呢?为Outer.Inner扩充接口?似乎也不可能吧。是的,这是JAVA 2的SDK文档中的例子,本意欲说明超类的显示构造调用法则。却不料成了我用来质疑的范本。
话说回来,这也并非只是JAVA的过错。同样的问题在C++中照样存在:
class Outer {
public:
Outer(){
_tprintf("Outer()\n");
}
class Inner{
public:
Inner(){
_tprintf("Inner()\n");
}
};
Inner inner;
};
class ChildOfInner:public Outer::Inner {
public:
ChildOfInner(){
_tprintf("ChildOfInner()\n");
}
};
我只好说,语法允许这样子做,但这样做是不明智的:需要派生嵌套类的子类的情况,百年也不会出现一次。JAVA这次被我揪出来当了靶子罢了。
看看,JAVA的语法在做了那么多的限制之后,却反而在这里网开一面,让这种语法得以生存。这不是也挺奇怪的吗?
---- 指针 ----
指针真的惹祸吗?
是的,指针真是害人精。一个资深的C++程序员,也决不敢说自己对于指针的运用已经无懈可击了。
从C开始,让人千转百徊的,还是指针。从指针申发开去,多少精巧而简明的算法就此诞生。并且从此以往,给计算机历史带来了多少的生机。如果指针惹祸,不知今天所有的各式各样的操作系统该做何解?
不要忘了可以武断一句,现今运行的OS们, 100%都是C或C++加上ASM写就的。
用不好指针的人怎能责怪C++不好?
不要求你使用指针毫不出错。但是,运用不好一种语言的机制和特色,怎能反而责怪这种语言不好?因为运用不好指针,从而责怪这种语言总是造成内存泄漏,这种逻辑是极为荒唐的。
从另外一个方面来看,同样是一种C++,你可以有不同的运用方法。精深的程序员可以书写高级指针应用,而刚入门的程序员大可以利用各种成功的类库,尤其是STL来解决常用的例行开发,从而避免无法善用指针而带来的恶果。
所以,技术上的垂髫竟然挑剔技术,通常我们只能一笑置之,他毕竟还不免有点幼稚,看不清全貌是可以被接受的。
用不好指针的人是否可以被称为合格的C/C++程序员呢?我没有确切的答案。
GC=Garbage Constructor?!
从GC的表现来看,的确是一种垃圾。没有节制的吞噬内存,基本上同样是一种失败。
企图指挥GC足够正确的及时回收内存,是一种奢望,因为动态的拣选无用内存的算法,还达不到足够的聪明来保证无用内存能够及时回收。
对于24×7的实时工作,目前的JAVA表现将会不尽人意:你可以通过特别的申明来强制GC启用,然而你仍然无法控制GC指哪打哪,GC会顽固的停滞不前,直到内存终于耗尽时,它还可能并不干任何事儿(JAVA 1.x中,finalize()从未被象JDK文档中宣称的那样工作过,反倒是无计其数的文章指点出不可以依靠 finalize()来完成你可能不得不必须要做的清除动作;JAVA 2中的GC真正的“勉强”符合其文档上的号称了,却更容易造成振荡*)。
JAVA为了防止不正确使用指针而带来的后果,付出的代价沉重而昂贵。这仿佛20年代的女人袒胸露背一样,过分超前,适得其反。
如果计算机的硬件条件进一步扩展,假定可预见的5年之后,我相信GC付出的代价将不值一提。而作为今天,无论美国,中国,世界,都还是小公司多数的情况下,你难道能要求他们都买下RS6000?
从这一点看,SUN是在迎合巨型公司的口味,却又要立下牌坊,就不免有点那个了。
于是,有人换了角度,问我跨平台的问题。
---- 跨平台 ----
当90%的桌面使用Windows的时候,跨平台真的很重要吗?
我不想在这里讨论MS公司的问题,那是另一篇文章的内容。或者,为防止这个话题被无限展开,主题流失,我应该拿掉Windows的字样,改成MAC OS或者Solaris,怎么样?
90%的桌面使用Windows的时候,SUN是不太高兴的,要谈跨平台;
那么,当90%的桌面都使用Solaris的时候,SUN自然笑开了花。
但是,那时候,跨平台还有多大意义?猜测一下,那时候SUN还会跟你谈跨平台么?善良的人们啊!
再来看跨平台的能力,
JAVA就是独此一家?
不是的,C和C++都具备这样的可移植性。真正的程序员随手一抓,诸如PHP、APACHE等等,都是工作在多种平台下的源码。
不错,C++要想跨平台并且基本不修改源码,是不可能的,同时作为一种高级编程能力,大半的“C++程序员”都还不能完成这项任务。这里既有历史因素,又有客观原因。C++的实现版本实在过分的多了,为了给予程序员更灵活操作硬件的能力,各种编译器的自定义扩展也各执一词,这是当前C++源码想要跨平台工作的难点。
反观JAVA,作为寡头统治,号称一次编写,其实是一种未成气候的独裁罢了。今日的JAVA编译器实现,也已经有了若干版本。诚如我们猜测的一般,版本多起来,跨平台也就弱下去。还不必提起唯SUN独尊时直至现在,JAVA也根本没有确切的达成一次编写的目标。
不论怎么看,这种一次编写都更像一种笑谈,一个迎合部分人心的广告术,一个金玉其外的幌子,败絮其中。
达不到的目标,不要用来欺瞒他人,这种机巧只是违法和不道德的,不是其他的什么。
---- GUI ----
不想多提,反正JAVA弄出来的界面总是那么的难看。这不是习惯的问题,而是JAVA设计人员漠视GUI设计和人性化的结果。同时,当然这也是JAVA不够成熟的必然结果。
例如快捷键的设计,默认按钮,焦点切换等设计,例如色彩搭配,例如工作空间布局和占用的问题,从 Swing开始就失败,所以基于JAVA基础搭建的应用程序几乎统统都有非常可怜而不友好的界面,粗糙而简陋。哪怕是JBuilder这样的重磅型产品都不能让人足够满意。
---- JAVA之得意之笔 ----
JAVA的得意之笔还是极其的多的,我只列出下面三条,更多的不再罗列了,这篇文章并不打算成为论文的。
数组
JAVA最值得被称道的,或许应该是返回数组的功能。不要考虑JAVA是怎样实现的,仅仅观看这一能力:C++中返回数组会带来相当多的生存期问题,为了防止弊端,可能不得不强问题复杂化。JAVA的这一能力使得程序员能够更为自由的运用特别方便的算法,实在功不可没。
GC
前面提及GC的弱点,但那并不是我们的唯一观点。作为一种机制,GC是具有前瞻性的一大提高,这从现在的新鲜出炉的各种东西都不约而同的提供GC机制就可见一斑。由于GC的存在,程序员可以放弃对更多细节的关照,从而把精力放在对商业逻辑的设计上,这是GC的绝对贡献。
(自然,前文表述了我的个人观点:GC是先进的,但也是青涩的,现在就吃,会掉牙的。我自认能够很好操作指针,所以这是个人观点,不想妄求赞同了。)
体系
前面没有提及半点有关体系结构的文字。这是因为C++本身作为编程语言,并不涉及到系统设计方面的问题,但JAVA的完整内涵,却包括了大量的“固定且公认”的设计规范和体系结构。
对于一个典型的商业应用,利用AppServer提供底层框架支撑,JDBC提供异质数据源的接入,各种工作流服务随时就绪;JNDI提供统一规格的命名式通用访问;等等等等。这些,为开发打下了良好的基础。
自然,传统看来,这并不属于编程语言应该关照的内容,我也不再过多讨论。
作为一个完整的解决方案和体系,这是JAVA独有的优势。也是它的强势之处。
作为JAVA的方便性和强大,例子还很多。请注意我们的立场:作为晚于C++这么多年之后,并且参考C++ 的各种优点之后推出的新的语言,如此“多”的强大却也还是不免太少。
---- 初学者的误区 ----
“真的一次编写就足够了”。那样,能完成的任务可能会太玩具,没有多少使用价值。注意:不要片面理解这句话的含义,也不要把广告辞当作是真实世界。
“没有的指针,就不会犯错了”。哪里的话!还是有大量的事情需要你去担忧:需求采集足够和准确吗?还能适应今后的足够长的需求增长吗?体系结构设计合理吗?类的设计和选择够弹性吗?算法选择适当吗?分支逻辑正确吗?成员还没有初始化?是不是还没有连接网络?是不是没有考虑校验用户的非法数据?磁盘空间不够了怎么办?设计文档符合你的代码吗?你的代码符合设计文档的要求吗?能够在窗口(表单)上摆布两个控件,并不是程序员,更不要提是不是真正的程序员,这只是末流而已。
“人人都能编程”。最大的谎言,这个梦想永远不能实现:技术进步的同时,对人的要求也在进步。昔日诸葛能看天气是为诸葛;今天任何人收听电台电视上网都能知道天气,并不代表人人都是诸葛了。
“JAVA简便易学”。为什么人人都愿意相信谎言而不正视事实呢?这和C++简便易学、VB简便易学一样,都是古怪的。总是有人妄想不作付出,而有收获。可叹!
“国外公司都使用JAVA进行开发”。是吗?几百万的VB程序员们啊,站出来让伊们看看。然后,我们再来考量一番全球能有多少的职业程序员,比较比较JAVA程序员的真实数量,可好?事实是,且不论开发的人数和质量,只管聚焦这样的真实:国外也不过是有名有姓的极少数公司已经足够成熟的使用了 JAVA来构建自己的整个企业信息化平台。初一看这倒也不可思议,其实也挺正常,历史和性能,还有成熟度等等的原因。并不是有几百万个程序代码的片断就代表了语言的好坏,企业计算需要考虑的问题并非这么的轻率的。
全球500强的工作模式适应你的公司的环境吗?因为500强中的几家或者几十家使用JAVA系统,因此你的公司也应该使用JAVA系统?
“能做出来就好”。我很不以为然,持这种态度的人,将会被我骂死。我没有什么民族产业那么的高度,却讨厌这种不负责任的态度。所以,中国大陆的开发总是恶性循环,没有质量,进而没有进度;没有进度和质量,于是没有订单;没有订单,好不容易居然有了,于是进一步的要求,赶紧搞出来吧,谁叫咱没有效率呢;于是再度没有质量和进度。最后,没有象话的东西示人。这时候,个人力量已经微不足道了,只好任由一步一步的衰败下去吧。
---- 结束 ----
JAVA的路还很长。
要想真正具备实力,JAVA还有很长的路要走。JAVA仍是一种不成熟的规范。
简单列举一个例子:嵌套类是一种有用的模型,JAVA生产的嵌套类总是OuterClass$InnerClass这种命名方式,注意到这在相当多的UNIX平台中会有问题,因为UNIX通常使用$符号作为命令行提示符。 Solaris本身就是UNIX的变种,而SUN居然遗留这种问题,不能不让人怀疑其素质或者敬业心等等。
(现在不必担心名字与提示符冲突的问题了,今天这已经不是问题)
再如:请参阅Thinking In Java一书第六章关于final处的论述,那里精辟的反驳了JDK 1.x中令 Vector不能被用户复用的不足。
注意到JAVA 2中这一不足已经被调整了。在会心一笑的同时,你应该充分正确而完整的认识到JAVA的不成熟。
SUN并不打算保护你在早期JDK开发方面的投资,重要的是,SUN的投资和那几十(?)位Java、 JDK的设计者的偏好更为重要。而当时的JDK和现在的JDK,也许可以不过分的称一句已经翻天复地的变化了,若干早期代码在不算久的今天已经有了“标准”的实现。
一个小小的例子是generic,让众多的支持者们热切期待JAVA版本的模板机制能被实现。这些支持者等到了 JAVA 2,却发觉没有generic关键字的踪影了。可以预期,对此,SUN会说模板将事情复杂化了,所以不计划支持这种不简易的东西。
这和MS不同,MS并不是C++的负责人,而MS这么多年以来,在自身产品的兼容性方面承受了相当多的代价。更何况SUN的文档要和MS相比较的话,简直提鞋都不够。JAVA的STL的更优秀的版本不是由SUN生产的,JAVA文档的索引还是JBuilder之类提供了真正的检索和目录。
对于我个人而言,刚开始做JAVA的各种软件包的配置简直是恶梦,看看已经毫无差错了,偏偏还是找不到类,如今回首,当然可笑了,但这样可不叫易用。
SUN可能应该反省一下自己究竟够不够资格做JAVA的监护人。你已经知道JAVA在企图面面俱到,处处都有 JAVA的身影,也处处都遗留问题。而SUN真的独力足以支撑么?还是死抱着许可证不放,有什么开放可言?这就是司马昭之心了。
我才不介意SUN有没有野心呢,我只想怀疑SUN这个至今仍靠硬件产品为生的公司,有没有那么强大的实力来完成JAVA一统天下的夙愿。
而进一步的,真的一统天下,是福兮祸兮?SUN能够就此千秋万载?
对于一个发展中的规范(JAVA已经不仅仅是一种编程语言了),我在前文中不留情面的偏激地进行了斥责。我真的要向你强调,在盲从JAVA前,还是应该细细考量。
JAVA中还太多BUG,偏爱它的人往往并不正视这些问题,作为严谨的程序员来讲,这是令人失望的。
JAVA给我们带来了小部分技术的前瞻,尽管略为超前,却是可贵的。然而,站在前人的经验之上,仅仅如此之少的改进,还是让人不能满足。
SUN公司只是不成功的枭雄,在商业上的不成功之处也怪多的,何况早有迹象显示出它的野心勃勃。从这个意义上,争论JAVA是否优秀还是比较浪费的。甚至夸张一点,JAVA前景堪忧。
天下大势,分久必合、合久必分。JAVA要想保持Pure,本身就是违背规则的。而一旦不能保持,百花齐放之下,今天JAVA吸引眼球的众多特色将会损失殆尽。
---- 再论垄断 ----
很多方面的经验告诉我们,唯一化的选择只能由集中强权才能保证,是为垄断。
象一次编写,唯一规范等等,都有这样的背后不为人注意的空白之处。细细思量之余,当可发现,午餐晚餐都不会免费的。
---- jy附言 ----
为了可比,本文只侧重考虑两者作为编程语言方面地一些局部状况,见解不高竿,自然毫不意外。
这方面地讨论已经很多版本了,我并未提出什么特别独有的思想出来,也不必对我有此奢望。
前一段时间因为爱好和需要,转入JAVA中学习,一方面是不信邪,我咋的就学不会那;一方面还是不信邪,JAVA这么好,真的能让人象大跃进一般。于是,这篇不过是学习笔记的感想就出笼了。
由于其实是笔记,语气不免尖刻一点,算是我的坏德行好了。
最后,感谢你阅读此文,浪费您的时间真是遗憾。