这是一篇来自中国Java开发网的帖子,很老的帖子了,2003年的,那时我还不知道Java是什么玩意呢。由求max而引出的一系列讨论,感觉相当有意思,各抒己见。我发现自己对于这样的论坛特别的情有独钟,像中国Java开发网、啄木鸟社区、看雪论坛。。。虽然这些网站没有现在的一些论坛那么高大上,那么炫酷,但是特别实在,也特别有深度(我不是来装逼的),也可以说见证了中国软件开发的历史(这个有点 瞎BB了~~~)。扯多了,来看看这篇帖子吧。看看你有什么想法吧,接受挑战吧。别怂,就是干!!!
原帖:
首先说明我是一个C++程序员, 其次我不好强也不好斗,我不想挑起事端, 我发此文章只是想了解一下JAVA程序员对一些东西的看法;比如大家大部分都说JAVA要比C++更OO, 是一种OO更纯的语言(相对C++来说), 当然我不否认这一点。
《人月神话》写道:"《没得银弹》被证明富有煽动性的, 它预言十年内没有任何编程技巧能够经软件的生产率带来数据量级上的提高, 十年只剩下一年了,我的预言看来安全了。"这是写于8年前的1995年了,如果我没有记错的话,C++应该是生于1970年代,但C++标准却一直到1998年才定下来,而JAVA出生于1991年, 那么OOP发展到现在,到底会给我们带来怎么样的提高?
我很想请教各位JAVA好手,作为当今世界最为OO的语言 -- JAVA是怎么解决这个简单的问题的:求最大值:max.
当然这不是我提出的问题,这是1995年1月,Scott Meyers在他发表于C++ Report里的一篇名为《min, max and more》[1]的文章里,对C++社群提出了一个挑战。在仔细地分析了基于宏和代表当时模板技术水平的实现后,他得出结论:
那么究竟什么才是最好的方法——正确的方法——来实现max ?借用Tevye 的不朽名言来说:“我告诉你:我不知道。”面对以上的分析,我越来越觉得我是在告诉人们使用宏的方法可能是最好的,但我讨厌宏。如果你知道max 的一种优雅实现,请告诉我。
据我所知,直至今天这个问题跟N年前一样富有挑战性。各位有请----
下面的是原帖的讨论和回复,很精彩(我是这么认为的~~~):
rainman:
why:Java里是这样子的:
max = Math.max(a,b)
蛮优雅
> 如果我没有记错的话,C++应该是生于1970年代
看怎麼定義「生於」吧。
C 是生於1970年代,而 C++ class 的概念則源自更古早的 Simula67,operator loading 則源自 Algol68,Exception handling 則是1970前後的 Ada 、Clu 和較近期的 ML。純粹從概念的成立而言,C++可算是1970年代的。
但現實中 C++ 的前身,C with classes 應是 1980年後的事,C++ 在1983年才正式出現。
> Java里是这样子的:
> max = Math.max(a,b)
nullbi 所指的是 macro (= 宏?) 的 max,即
或 generic, template form, 例如#define max(a, b) ((a) > (b) ? (a) : (b))
Java 沒有 macro,generic 要到 Java 1.5 才可能有,而且和 C++ 的 template 分別不少。而且 Java 也沒有 operator loading,所以不太可能那樣簡潔的 max 和 min,但問題是,有這個需要嗎?template <class T> T& max(T& lhs, T& rhs) { return lhs > rhs ? lhs : rhs; }
程式語言需要優雅但複雜,還是簡明且實用呢?
Scott Meyers 的 "min, max and more“:
http://aristeia.com/Papers/C++ReportColumns/jan95.pdf
software_young:
所谓“萝卜白菜,各有所爱”,很多事情并没有最佳的解决方法,有的只是偏好、需要和现实的妥协。
我不认为Java是比C++更纯的OO,而觉得Java是C++的简化版,没有了多重继承,没有了那些重载,没有了指针,也没有了模板,什么都是简简单单的,简单到了看看Sun的Tutorial就可以编程序的地步。也许这是Java能够迅速上手的重要原因,也许就是因为这个,微软的C#整个就是抄袭Java,当然类库除外。
就语言的OO程度来讲,Java和C++可以说是各有千秋。Java取消了C++的来源于C的非OO部分,把一个函数森林变成了一棵Object树,但是它同时也取消了C++中那些精妙的地方,没有了多重继承和模板,单靠单一继承加Interface,有些事情的确是难办。JDK 1.5中据说要加上的Generic可以说是对最初Java设计思想的一个反动。反动不一定是坏事,当然也不一定就是好事,像JDK 1.4加上的Assert可以说就是一个败笔。
software_young:
在OO世界里,generic是一个重要的方面。在这个方面,SmallTalk做得最好,可惜它不能够商业化。
做到generic有三种方法,一个是SmallTalk那样彻底的,一个是C++那样补充完备的,再一个就是Java目前通过JGL之类软件部分补充的。前者当然是理想的,中者是现实的,而后者则是勉为其难。我的项目必须用Java,但是又大量涉及到generic,因此只好用JGL来弥补,充分领受了夹板气。
相对于微软的东西来说,Java可以说是开放的(我必须这样说,否则从这里收到的板砖足够我盖座大房子的了),但是相对于Unix(各家有各家的,彼此几乎没多少关系),它则不够开放,甚至也比不上Linux的开放程度(根源是一样,但是各个发布商的产品之差别也够可以的)。目前Java的语言,J2SE和J2EE还是被Sun一家公司控制着,语言的标准化不成问题,但是服务器端各个厂商的实现则有相当的区别(不管是描述符还是应用代码),以至于服务器端的应用几乎是不可能跨厂商的(除非你做大量的修改)。
JDK1.5中将会加入的generic的特性,我还不是很清楚。那个版本将是明年的事情,目前还处于Prototype Implementation阶段,无法实用。由于项目压力,我没有时间去关注。
Math.max()可以对应处理double、float、int和long这四种数据类型。
我不是说抄袭不好,而且也不是在说微软的坏话,事实上这里的创始人和斑竹们中的几位很知道我是亲微软的,并为此对我颇有微词。但是应当指出的是,C#和Java实在是太像了,以至于一个熟悉了Java语言的程序员可以非常轻松地熟悉C#;当然C#中的Delegate不是抄的,那是微软的原创,它最初在Visual J++中出现,后来就在.Net的编程语言中借尸还魂了(当然后来的这个做得好多了)。个人认为Delegate是C#相对于Java的一个优势。
我不认为一种语言会完胜另一种语言,问题的关键不在于技术,而在于市场需要。Windows编程技术发展到今天,还有很多人依然在用Win32 API而不用MFC就是明显的例证。同时,C、C++、Java和C#这些语言都在普遍地使用中,很难说谁完胜了谁。
rainman回复software_young:
JGL???? 不知道你是不是真懂哦,JGL只是一个第三方使用STL风格的写法的通用容器和算法类库(现在已经是收费的了,所以我不用)。Java现在已经有Generic的扩展了,做得最好的是:GJ: Generic Java, http://www.research.avayalabs.com/user/wadler/gj/ ,JDK里的容器类库已经全部用GJ重新实现了,来验证泛型Java的健壮,效率。
To nullbi(原帖作者ID):你可以在上面网站下载源代码来看GJ代码是否优雅。因为使用GJ对JVM不做任何要求,而且GJ Team做得足够好了,所以JDK1.5是否要包括Generic才被提到日程上来讨论。
再回到Max的问题上来:
比如求一个List里元素的最大值,GJ可以这样写:
interface Comparable<A> { public int compareTo (A that); } class Byte implements Comparable<Byte> { private byte value; public Byte (byte value) { this.value = value; } public byte byteValue () { return value; } public int compareTo (Byte that) { return this.value - that.value; } } class Lists { public static <A implements Comparable<A>> A max (List<A> xs) { Iterator<A> xi = xs.iterator(); A w = xi.next(); while (xi.hasNext()) { A x = xi.next(); if (w.compareTo(x) < 0) w = x; } return w; } } class TestCase { public static void main (String[] args) { // byte collection LinkedList<Byte> xs = new LinkedList<Byte>(); xs.add(new Byte(0)); xs.add(new Byte(1)); Byte x = Collections.max(xs); // boolean collection LinkedList<Boolean> ys = new LinkedList<Boolean>(); ys.add(new Boolean(false)); ys.add(new Boolean(true)); Boolean y = Collections.max(ys); // 这里编译的时候会出错, // 这样非常好, //传错参数的可能性就不会有了, //交给编译器来做检查省时间啊。 } }
限于篇幅的原因,讨论就到这里了。如果想看原帖的话,狠狠点击 这里。<span style="font-family: Tahoma, Georgia;"></span>
<span style="font-family: Tahoma, Georgia;"></span>
祝大家新年快乐!