如何解决 Java 语言的十大问题
事实上,在我的经历中,我总是不得不面对 Java 的设计和规范上的一些错误,缺陷和不足, 这些东西, 让我的 Java 程序员生活少有乐趣可言. 现在全世界的 Java 程序员有数百万之众, Java 写就的代码更达数亿行,要是我说 Java 在不久的将来死去,这还有些远.不管怎样, 随着一些兼容 JVM 的语言出现(我最钟意 Scala)后,这些问题变得越发不能容忍了,我开 始想,是时候慢慢离开 Java 了(但并不脱离 JVM).具体说来,我认为 Java 语言的 10 大问 题是: 1,缺少闭包(closure):我想这个不需要解释了.函数式编程已经存在几十年了,但最近 几年,它们获得了越来越多的关注,最主要的原因,是它可以自然地编写并行
程序.我部分 的同意 Joshua Bloch 强调在 Java 中引入闭包的问题需要再想一想(BGGA 提议的方式真的很 糟),至少闭包的缺失,使得在 Java 中做任何真正的函数式编程都是不可能的. 2,缺少一等函数:这个问题与前一个有些关联,但我认为它更糟糕.在 Java 里,要达到类 似效果的唯一方式,是使用著名的,丑陋悲惨的单方法匿名内部类,但这看上去的确是一个 拙劣的方法.甚至在 C#中,也通过代理机制,提供了一个更好的实现. 3,原生类型(Primitive types):如果在
Java 中一切皆对象,那是多么完美啊,但他们偏 偏不这样
设计. 因而, 这一点导致了一些问题, 比如, 不能把一个 int 放到集合 (Collection) 里,这个在 Java5 中通过自动装箱特性得到了解决(下面会提到).它也造成了传值与传引 用上的困扰,原生类型数据是通过值传给方法的(复制一份拷贝,然后传给函数),而真正 的对象是通过传递(译注:其实是复制对象地址再传递,因此应该也是传值方式,只是由于 函数内部可通过这个对象地址访问对象,因此效果上类似传引用). 4,自动装箱(Autoboxing)和自动拆箱(autounboxing):这个特性是为了解决因原生类型 的存在所导致的
问题,在 Java5 引入的.它允许静默地转换原生类型到相应的对象,但这常 常导致其它的问题.比如 Integer 可以为 null,但 int 不能,因此这时 JVM 只能抛出一个难 以调试的空指针异常(NullPointerException).此外,它还可能导致其它奇怪的行为,就 像下面的例子,我们就很难理解,变量 test 为什么是 false: Intger a = new Integer(1024); Intger b = new Integer(1024); 1. boolean test = a < b || a == b || a > b; 5,缺少范型具类化:范型是 Java5 引入的一个很酷的特征,但是为了保持与旧版本 Java 的 兼容性,导致缺失某些重要的特性,尤其是不能在运行时反省范型的类型.例如,你有一个 方法,接受 List< ?>参数,如果传进来一个 List< String>,你却不能知道运行里该范型的 确切类型.同理,你也不能创建范型数组.这意味着,尽管下面的代码看起来很
自然,但却 不编译不了:
1. List< String>[] listsOfStrings = new List< String>[3]; 6, 不可避免的范型警告: 你有发现过自己陷入不可能去掉的关于范型的警告么?如果你像我 一样大量使用范型,我打赌你碰到过.事实上,是这个问题的规模化症状,让他们认为需要 引入一个特定的注解 (@SuppressWarnings("unchecked")) 来处理这种情况,我觉得,范型 应该可能被设计的更好. 7,不能传 void 给方法调用:我得承认,这种给方法传递 void 的需求,乍一看有些怪异.我 喜欢 DSL,当我实现自己的 DSL 库(lambdaj)的一个特定特性时,我不得不需要一个方法声 明成这样的签名:void doSomething(Object parameter),这里为这个方法传进来的参数 parameter,是另一个方法调用的结果,它唯一的目的,是
注册调用(的对象)自身,以可以 在以后执行它.让我吃惊的是,即使 println 方法返回 void,看上去也并没有一个好理由, 不允许我把代码写成这样,: 1. doSomething(System.out.println("test")); 8,没有原生的代理机制:代理是一种非常有效和应用广泛的模式,但 Java 提供的代理机制, 只