Skip to main content

Why Java Sucks and C# Rocks(1):比较的意义与目的



原文 - Why Java Sucks and C# Rocks(1):比较的意义与目的

消息发布之后, 许多朋友都表示对我这个主题的关注——无论是正面还是负面的——这让我很高兴。不过说实话,我原本并没有打算写这篇文章。我原本的打算是从一开始就进行技术方面的讨论,但是大家在前文的反馈让我把一些问题想得更清楚了,也认识到有些东西可能需要先说在前面可以有更好的效果。希望各位朋友可以继续给我一些反馈,这样我可以在必要的时候进行补充更完整的内容。这次的话题很有价值,我想把它做的更好。

为什么是Java?

这个系列我将详细比较C#和Java——语言,而不关Java平台任何事情。其实这本不想强调这一点,因为语言和平台之间是没有任何可比性的。因为C#明显只是一门语言,因此根据“类型推断”,则Java也应该是“语言”类型才对。因此,我在标题中就不想加入“Language”这样较长的单词了,累赘啊!

那么,我为什么选中Java来和C#进行比较,而不是其他语言呢?原因很多,主要有以下几点。

首先,Java语言足够热门。看看TIOBE语言排行榜,Java语言风光无限,从2002年开始几乎全程领跑。如果我说这门受众如此之广的语言一些坏话(好吧,其实是很多坏话),那响应的人一定会非常多。例如,事实上Delphi语言在停滞发展之后,在我看来它也已经和Java处于同一级别了。但是我不想说Delphi Sucks,因为即便这么说,可能也不会有多大影响力——当然,可能在盛大创新院里会正好相反。

其次,Java语言真的很糟糕。好吧我承认,它在诞生初期还是有重大意义的,它简化了编程难度,大大提高了生产力。但是,由于它多年来的固步自封,它已经完全跟不上如今时代的发展了。用现在的标准来衡量Java语言,会发现它是如何拖累程序员的生产力,如何成为Java平台上最短的一块木板。作为一次关于语言比较这种“争议性话题”来说,如果不是有一方“全面落后”的话,那一定就会陷入双方粉丝的口水战——掺杂大量主观内容的讨论,那倒真就没有任何意义了。

还有,知道Java语言有多糟糕的人并不多。可能有不少朋友的确会感觉Java语言在使用时“挺啰嗦”的,但是由于并没有去仔细了解其他语言的的发展情况,对Java语言的糟糕之处也说不出个所以然来。但是大部分人,真的是大部分,他们一直认为Java是一门不错,甚至很优秀的语言了。为什么?看看排行榜咯。但是我想说,排行榜只能说明它的“热门”程度,并不能代表Java语言有多么优秀。正所谓“劣币驱逐良币”,我这个系列的文章也是想告诉坚持Java语言的程序员们,您到底损失了什么。

更重要的是,那就是Java虽然糟糕,但还是有解决办法的。如果没有解决办法,那么这场讨论的价值就会大打折扣了,因为讨论了半天我们还是只能保持现状。例如,C语言生产力高吗?当然不如如今许多高级语言。但是,C语言是不朽的,因为我们必须有一种语言来负责底层的开发,这要求它和冯·诺依曼结构尽可能的对应,而不能有太高级的抽象(因为一高级就难以生成最为高效的机器码了)。因此,我不会讨论C语言的特性,我会选择Java语言。当然,这个解决办法就是抛弃Java,换用一种生产力更高的语言。

最后,好吧,其实还有一点便是,我对Java语言足够熟悉。我的“职业程序员”生涯便是从Java开始的(之前都算是小打小闹),大学里的编程课学的也是Java(期末考试时是全班最高的106分,满分是100+10分附加题),也用它做了不少项目。我还记得最后一个Java项目是2004年参与开发的是海关审批工作流,当时翻来覆去看的参考书是《J2EE Development without EJB》。只不过接下来我便投身于.NET世界,用的最多的语言便是C#了。C#从2.0起突然发力,瞬间将Java语言甩开几条马路,而3.0的改进更是堪称经典。不是我不想回到Java平台,是我实在不想在Java语言上浪费生命。

嗯嗯,其实我也挺希望许多朋友在批评一个事物的时候,先对它的现状有足够了解的。否则,真挺没意思的。

又为什么是C#?

好吧,那为啥要拿C#出来耍?直接说Java的不是就行了嘛。其实我也有几点理由:

首先,我的博客毕竟还是主要关注于.NET技术的,来看我文章的大部分朋友相信使用的还是C#语言。我这一系列文章虽说是要讲Java烂,但可能大部分“手法”是在说明C#和Java语言之间的差距。因此,我也会努力地在文章中体现C#的美妙之处,会展示大量C#的编程模式。这些模式并非只是为了好看,而绝对是在生产过程中非常有用且常用的。我希望这系列文章除了鼓励别人摆脱Java语言的负累以外,也可以给C#程序员带来同样的价值。

其次,我想改变许多朋友对C#的看法。我想大部分朋友应该了解C#语言比Java的特性多,但是您可能不太了解C#目前的发展状况,以及C#和Java之间的真实差距。您可能会认为,C#虽然比Java特性多,但也只是一些语法糖而已,虽然可能的确比Java生产力来的高,但是优势并不明显。我想要告诉大家的便是,C#有别于Java的特性并非这么普通,它是凝聚了Anders Hejlsberg这个天才的理想,都是对生产力提高有重大意义的。

还有,如果要与Java语言进行比较,还有比C#合适的对手吗?我想不到很合适的。因为根据TIOBE语言排行榜的纪录,排名靠前的语言中也只有C#和Java颇为相似。这个相似体现在多个地方,其中最重要的在于它们所在的平台所面向的应用类型几乎完全相同。C#和Java语言也是纠缠如斯,相信这两者的碰撞会比其他情况带来更多关注。同样,至今还有些朋友认为C#只不过是在抄袭Java而已。不过我在这里想说的是,好吧我承认C#在最初和Java颇为相似(但也有许多不同),但是自从C# 1.0诞生之日起,就只出现Java借鉴C#特性的情况,至今已将近10年。您可以记住这句话,我会证明给您看的。:)

当然,我对C#也足够熟悉,我想这点就不用多做解释了吧。

LISP那点事儿

呃,我在表示要写Why Java Sucks and C# Rocks系列文章后,收到的许多质疑是有关LISP的。LISP是一门(或者说是一类)神奇的语言,虽然在工业界的应用并不广泛,但是却有着不容置疑的历史意义。我有幸在大学时加入了复旦大学软件学院和爱尔兰都柏林大学合办的所谓“爱尔兰班”,开办的第一门课便是函数式编程,使用LISP讲解(不过现在的同学已经使用Haskell了),于是我在那时候也对LISP产生了一定的兴趣,也有了大半年的学习接触。虽远不能说是精通,但基本的了解想必还是有的。

关于LISP,有种说法便是“LISP之后,再无创新”。于是有朋友说,那么你不谈LISP,在Java和C#之间比什么劲儿嘛。首先,我想上文也已经表现了我的一部分想法了,现在则再谈一些。其实我觉得这种说法就好比说“某某人已经是第一名了,后面的争夺又有什么意义呢?”,这个说法显然是不妥当的。语言的争论和评价从来不曾停止,即便是大师们,例如Linus炮轰C++,高司令谈C#,Anders认为Java的泛型不好,Matz在邮件列表中戏称Ruby为MatzLisp,这些都是有趣的,有价值的,值得关注的东西。

也有朋友说,有什么语言能带来LISP那般革命意义,能够代替Java呢?LISP的确有其革命意义,但是语言的确知道它的缺陷,因此也就主要是把它供在神坛上,需要的时候膜拜一下便是,紧抱不放便是问题了。语言同样在不断发展和演变,尤其是对于工程应用来说,人们对于生产力的追求永远不满足,这点从业界关于语言的会议(如Lang.NET)便可得知。而即便是如IFL这类专注于函数式编程的学术会议,对于LISP语言本身的关注程度也有所降低。人们都知道,是该站在LISP的肩膀上向前看的时候了——其实很久以前就是这样了。

而且,我的目的主要还是想鼓动大家抛弃Java语言,这和它的替代者是否革命意义并没有关系。这就好比,对于石器时代的人们来说,第一根铁棍的革命意义远超后来的神兵利器,但是人们什么时候放弃过对神兵利器的追求呢?只要真正是“更好”的东西,那也就足够了。

我也是个俗人,讨论讨论对真正生产有直接影响的东西,也就够了。

糖、糖、糖

再回到关于“语法糖”的讨论。之前提到,有不少朋友认为C#相对于Java只是语法糖较多,够甜。但事实上,我在这一系列文章中并不想提“语法糖”这些东西。嗯,我是说,我眼中的语法糖。

从理论上说,只要是图灵完备的语言,就不存在“能力”上的根本差异,任何工作都是可以实现的。但是我们使用的语言,往往也会影响,甚至决定了我们的思维方式。因此一门语言的关键,我认为就是它的思想,或者说,是它对我们“思维方式”的影响。同时,由于语言会影响我们的编程思维,甚至系统的架构设计,因此在我看来它也是至关重要的。

举个有些极端的例子,如果人们还在使用汇编语言进行开发,那么估计程序员的思维永远无法跳出“子过程”这个抽象级别,什么面向对象设计,函数式编程几乎无从谈起。人们在生产和学习过程种会引发一些需求,因而需要产生一些工具来辅助学习和生产,而“语言”便是此类工具之一。只有利用高级语言,人们才能有效地把真实世界抽象成计算机这些机器盒子能认识的东西。

如今,可用于构建项目可选的主流语言往往都会有多种,有时候我们的确会发现,好像不同的语言——例如Ruby和Python——从各方面来说并没有太大区别(或者说优劣之分)。这是比较正常的,因为某些(甚至是大部分的)语言特性,并没有对我们的“思维”产生影响。

举例来说,某些喜欢Ruby的朋友认为Ruby语言的编程体验非常良好,好比它的数组操作可以直接做加法或减法:

array = ['aaa', 'bbb', 'ccc'] - ['ccc', 'ddd'] 

或者说,在Python里交换两个变量的值也只需要一行代码(大部分语言中可能需要借助中间变量,好吧,我承认Ruby里也能做到这一点):

a, b = b, a

但是,就我个人观点来说,这些语言特性,虽然它们的确可以让编程工作变的相对轻松一些,例如可以让我们少些一点代码,但终究没有改变,或是表现出另一种编程思维。这样的语法特性,一般来说都可以通过构建一些简单的辅助函数来做到类似程度的“简化开发”(如上面Ruby的例子),对于那些非“即写即抛”的程序来说,这些特性的优势并不明显。就我个人来看,我并不会太重视这些内容。

而与此相比,Ruby的Mixin机制和Python的Decorator就不仅仅是“语法糖”,而是比较重要的语言特性了,因为它们可以带来或大大简化某些十分有用的编程模式。“简化”也是语言设计中非常重要的一点,我始终认为,一个语言特性只有真正“好用”,它才能被人们广为接受。例如,使用Java语言能实现Actor模型吗?能,但是它缺少Scala那样灵活的函数式语法,以及模式匹配等特性,因此无法构建出一个好用、易用的Actor框架,自然也就无人问津了。这其实也是“语言影响思维方式”的典型案例之一。

其实人们在LISP之后继续前进的原因,也是因为LISP虽然提出了许多编程理念,范式,但是每个都不够“好”、“优雅”、“简单”等等。做的“更好”便是其他语言不可忽视的意义。

是的,我不会强调C#如“属性”,“操作符重载”等语言特性,虽然它很多时候的确让开发变得简单,但是它们并不能改变我们的开发思维。那么这一系列的文章中我会重视哪些语言特性呢?我想,它们至少应该同时具备以下三个条件吧:

  • 必须是纯粹的语言特性:有人说Python方便,很多事情一个方法就能搞定了。这在我看来只是类库相关的东西而已。在这里,我并不关注类库与框架,我只关注纯粹语言特性。
  • 无法,或很难通过类库或框架弥补的差距:同样是一个方法能搞定的案例,但是如果这个方法必须借助特定的语言特性才能实现,那么这便是我的关注点。
  • 能够改变编程思维、或是引出额外的编程范式:正如上文讨论的那样,这是我最为重视的东西。

嗯嗯,就是这样。

再补充一些内容

好吧好吧,我知道您看到那么多文字之后也一定也想说些什么了,不过您再坚持一下,等我把话说完吧。

写这一系列文章的目的,我想已经说得很清楚了。不过我想我还是有必要强调一下,我并不想让您:

  • 立即抛弃Java语言(不过我希望您可以现在就开始准备了)
  • 使用C#来代替Java语言
  • 使用.NET来代替Java平台
  • 认为.NET平台胜过Java平台
  • 认为CLR强于JVM
  • ……

总之一句话:我没说过的东西,您也别多想。我说过的,您也不用怀疑我的“诚意”。:)

再来一些问答吧,如果有需要的话我也会不断补充一些内容的。

  • 问:语言的生产力,关键还是看熟悉程度吧?答:我不这样认为,很多东西的差距是实实在在,不容置疑的。例如,C语言的生产力就比汇编要高,电锯的切割效率就比手工锯条要好。的确,我承认使用者对工具的熟悉程度会影响生产力,但我想您可以想,就当您已经对两种语言都足够熟悉了,这时候总可以开始比较生产力了吧。不了解怎么办?学咯,“磨刀不误砍柴工”,有句俗话应该是这么说的吧。
  • 问:开发项目并不由语言一个方面来决定吧?答:没错,所以我也不认为您应该“立即”将Java语言抛弃。例如,假如您对它的替代品还不够熟悉的话,假如您的团队还是对Java语言有足够了解的话,假如您的老板决定非要用Java语言而您离开他又活不了的话……那就继续用Java咯。总之,项目的技术选型是个平衡的结果。我只是给您在语言方面给出建议而已。
  • 问:Java语言的替代品足够成熟吗?答:足够成熟。当然,它的社区资源肯定还不如Java语言,但我认为它也足够了。而且,如果我现在对它进行推广,那么它又会有什么发展,资源又如何增多呢?是啊我承认,我是个颇有理想主义的人。
  • 问:为什么不比较Java与.NET平台?答:因为在我看来两者实在难分高下,上文也说了,这样的比较几乎就一定会沦为双方程序员的口水战,因为没有一方可以拿出切实的证据来说服对方,大家主观对主观,实在不专业。当然,如果您感兴趣的话可以自己比较一下,我会适时跟进的。:)

好,该说也说得差不多了。那么从下一篇文章开始,我们就来一起享受技术带给我们的快乐——和挫折吧!

本文为 赵劼 发表在 个人博客 的系列文章之一。