Elliotte Rusty Harold / 文 [email]JaredQin@163.com[/email] / 译
2007年,SUN将松绑Java,使其在Java开发者社区的一个开源许可下发布。这篇文章中,作者Elliotte Rusty Harold预言了Java平台的新方向,涵盖很多方面,从代码编写,到Bug修正,到新的语法等等。
2006年同样是号角争鸣的一年,在同MS(c#)和脚本开发社区(Ruby)的竞争中,Java仍然是全球使用的最多的开发语言。Java 6的发布引来了众多的赞扬,但却比不上宣布Java将在GNU General Public License下完全开源。这股巨大的冲劲能否在2007年延续,让我们拭目和思考。
2007年的上半年,Sun将在开源许可下发布其JDK。开源JDK是Java开发者社区前进的一大步,它将驱动Java平台在下一个十年内的发展。
当程序员从简单报告bug转变为开始自己修正这些bug时,可以预想JDK的质量将有大幅提升。在Java Developer Connection(JDC)中报告bug将会包含详细的分析这些bug的危害,甚至提供修补bug的补丁。正如Linus's Law所说,“Given enough eyeballs, all bugs are shallow.”(毛主席早就说了,群众的眼睛是雪亮的)。调试可以并行去完成,优化工作也是。开源使得它们实现最大的同步。
分支
不幸的是,设计工作没有同调试和优化工作同步起来。一个清晰的API有时需要一个统一的领导,一个“独裁者”。然而,这些独裁者们,有时知道自己在做什么,有时却不知道。这些可能的独裁者之间的竞争,常常是解决问题的最好方案。
鲜有厂商能够为一个产品开发出足够多的独立实现来解决所有问题,而只能是一方面。但是开源社区可以在任何一个方面都繁荣起来。看看Java平台的在各个级别(语言,虚拟机,类库)上的分支。绝大部分都失败了,但这样是有益的。优秀的想法总会成功。一些可以延续自己的道路,一些会融合到标准JDK中去。也许明年这些还不能显见,哪一个分支会是哪种结果,但是这个过程将进行下去。
通过发行早期版本的Java 7 Dolphin,Sun在几个月内带动开源项目的运转。因为构建(build)的问题和(早期)许可的障碍,Sun不会发行更早版本的JDK,开源只针对 Dolphin。然而,第三方通过把Sun的版本分解,创造出可行的开源版本的Java 6,Java 5,Java 4,甚至更早的版本。
一些早期的分支版本可能与Sun公司的商标产生冲突,甚至接到不愉快的律师信。我们需要一个通用的,非商业化的,所有人都可以用的标志来命名这个语言。我提议用“J”,因为没有人可以将一个单一的字母申请为商标。
开源项目重来没有死掉,它们只是渐渐淡去,失去往日光彩。像之前的Blackdown一样,GNU Classpath, Kaffe和其他开源的JDK项目的开发者正转向其他的工作。如果一个项目还没有达到1.0版本,它在未来也许也不会做到。
前瞻Java 7
Dolphin在2007年可能不会正式发布,明年发布可能是一个比较切合实际的目标。也就是说,工作在进行,一些特性会作为早期的标准扩展,或者至少beta版本,初入人眼。
不幸的是,加入新特性和删除特性相比,前者正是太容易了。几乎不可避免的是,随着时间的推移,语言将变得越来越复杂,越来越令人困惑,这不是少数。甚至那些独立的看很好的特性,当相互堆砌到一起的时候,就会变得问题多多。
不幸的是,Java社区还没有总结出这个教训,他们轻视这个一贯会发生的崩溃。这里正好有些跟新的语法相关的事情,他们太cool,令语言的设计者无法抗拒,甚至它们没有解决任何实际问题。然而Java 7中对新特性的呼声很高,包括闭包(closures),多继承,和操作符重载。
我猜测,今年结束之前,在Java 7的beta版本中,我们会看到闭包,也许也能看到操作符重载(50%的机会),但是多继承根本不会出现。太多的Java是基于单根继承。没有非常有效的方法将多继承改进到语言中来。
当前,还有很多很好的语法改进方案放在桌面上,有些已经引起重视,有些还没有。许多提案集中在将像“getFoo()”之类的函数,替换成像“->”一样的操作符。
Lists
第一个可能是,用数组的语法来访问集合(collections)。比如,以下代码:
List content = new LinkedList(10); content.add(0, "Fred"); content.add(1, "Barney"); String name = content.get(0);
|
可以写作:
List content = new LinkedList(10); content[0] = "Fred"; content[1] = "Barney"; String name = content[0];
|
另一种可能出现的是,允许在lists中使用数组方式的初始化语法,比如:
LinkedList content = {"Fred", "Barney", "Wilma", "Betty"} |
这两个提案都可以通过一些小的编译器技巧,在不改变虚拟机的情况下实现。对于修订语法来说,这是很重要的。没有一个提案是无效的,或者需要重新定义现存的源代码,这些对新的语法来说,是相当重要的问题。
一种语言特性它如果能够对开发者的生产力产生实际促进的话,它就会被内建到语言底层中去管理表(tables)、树(trees)、图(maps),就像你在使用XML和SQL时遇到的那样。像Javascript的E4X项目和MS世界的Cω和Linq项目,他们是这种思想的开路先锋,但是Java平台却不是这样。If anyone feels like making a potential game-saving play by forking the compiler, here is a very good place to look.
属性
我们可以看到一些关于属性访问的语法规则。其中一个提案是,利用简便的“->”来调用getter个setter方。比如,一下代码:
Point p = new Point(); p.setX(56); p.setY(87); int z = p.getX(); |
可以写成:
Point p = new Point(); p->X = 56; p->Y = 87; int z = p->X; |
其它符号,包括“.”和“#”,也像“->”一样被提示使用。
未来,你也许会不得不明确地用属性(property)定义相关的域(field),比如:
public class Point { public int property x; public int property y; } |
我个人很支持这样。我希望Java平台能够接受更多的人性化的入口,这样我们可以实际使用公共的field。如果我们用同fields一样的名称定义getter和setter方法,那么读和写field的会被自动分解到对应的方法上去,这样的语法更简洁和更具弹性。
BigInteger low = BigInteger.ONE; BigInteger high = BigInteger.ONE; for (int i = 0; i < 500; i++) { System.out.print(low); BigInteger temp = high; high = high.add(low); low = temp; }; |
这样写,更加清晰:
BigInteger low = 1; BigInteger high = 1; for (int i = 0; i < 500; i++) { System.out.print(low); BigInteger temp = high; high = high + low; low = temp; }; |
这个提案可能没有坏处,但它也许会误导人们对这些class的滥用,导致native code性能的下降。
从JAR中取出JAM
Java 7将修正那些刺激开发者的很久远了的源代码,像可变class的装载和关联classpath。Sun正在着力用Java Module System(JMS)解决这个问题。数据将被存储在.jam文件中,以替代.jar文件。这是一种包含所有代码和原数据的superjar文件。非常重要的一点是,JMS将首次支持版本,所以你可以说某个问题需要Xerces 2.7.1,而不是2.6。也将允许你指定文件版本依赖(dependence),比如,一个JAM中的问题需要JDOM。还将允许你加载其中一个模块(module),而不是加载所有的。最后,它将支持一种集中化的存储,提供很多不同JAM的很多不同版本,你可以在其中选取你需要的。如果JMS开始工作,jre/lib/ext将成为过去。
包(Package)访问
我还希望Java 7能放宽一点对访问的限制。使得子包(subpackage)可以访问父包(supperpackage)的类中的保护(package- protected)域(field)和方法,或者,至少是那些明确声明为友类的。无论如何,这将使得应用被分割到多个简单包中,大幅提高可测试性。对子包的单元测试,我们不必为了测试他们,而将他们的方法公开。
文件系统访问
1995 年以来,文件系统的访问一直是Java平台的一个重要问题。十年以来,一直没有可靠的跨平台的方法来处理基本的拷贝和移动文件操作。至少对之前的三个版本的JDK(1.4、5和6),修正它一直是一个公开的问题。可惜的是,这些令人头痛但是必须的拷贝和移动文件API,被转移到不是很通用但是很吸引人的操作上去了,比如内存映射输入输出(memory-mapped I/O)。也许JSR 203可以修正这些,并且给我一个灵活可用的、跨平台的文件系统API。再一次,工作组将花费大量时间在,文件系统留下的,相对并不是很重要的异步I/O 上。明年我们就会知道答案。
试验 无论改变了什么,最好的方法就是,先在开源分支中实现出来,我们就能看出它实际产生的或多或少的不同。为了这个目的,Sun的Peter Ahè已经在java.net上启动了Kitchen Sink项目(Kitchen Sink Project)。目的是利用javac编译器的分支不断的去测试像这样的各种各样的想法。在Blog中写下某些得意的想法是一回事,把他们变成真正可运行的代码又是另一回事了。
客户端GUI
虽然不被很多人注意,但是Java平台在桌面软件中确实存在四五年了.比较多的桌面应用软件是用Java代码写的,包括RSSOwl, Limewire, Azureus, Eclipse, NetBeans, CyberDuck, 等等。他们几乎使用了各种不同的GUI工具包,包括Swing, AWT, SWT, 甚至是像Mac OS X上的Cocoa的平台相关的工具包。没法看出哪一个工具包会在明年战胜其他的,虽然Swing看上去,在保持用户本地话感觉方面做的比较好。
在Swing中开发,仍然很据挑战性,但是明年Swing Application Framework出现时候,情况将会大大改观。这个框架目前仍在Java Community Process中开发(JSR 286)。以下是JSR中描述的:
易写的Swing应用程序,倾向于让启动和关闭,让资源、动作和会话状态的管理具有同样的核心元素。新 的应用程序在启动是创建所有的核心元素。Java SE没有对结构化应用程序提供任何支持,这经常让新的开发 者觉得有点无助,特别是当他们企图构建一个比Java SE的文档中提供的例子更为深入的应用程序的时候。
规范(最终)将填补Swing应用程序在基础结构上的空白。它将定义一些小型的扩展类或者框架,这些框 架定义了对绝大部分应用程序来说通用的架构。
Swing Application Framework应该支持一个典型应用程序的绝大多数功能,允许开发者把他们插入在一些自定义点(比如开启和关闭)。在启动和关闭之间,它将处理保存和重新载入窗口和应用程序的其他部分。最终,它将允许开发者编写异步的动作,运行在Swing事件处理线程之外。
继续改进JavaBean和基于它的所有功能,包括Swing。JSR 295正在定义一个标准来将bean绑定在一起,这样对一个bean的更新将会自动反射到别的相关bean上。比如,一个GUI的grid bean会随着与之相关的数据库bean的变化而自动更新。
最后,JSR 303是关于一个基于XML的验证语言的,这个语言用来声明任何一个给定的bean可以使用的值。你可以声明一个整型属性必须在1和10之间,或者一个字符串属性必须包含一个合法的email地址。幸运一点,在年底前的beta版本中我们就可以看到它,在明年的Java 7中就会完成。