1,缺乏封閉性:我覺得這個不需要解釋。函數式編程已經存在了幾十年,但是最近幾年,它們獲得了越來越多的關註。最主要的原因是它可以很自然的編寫並行程序。我部分同意Joshua Bloch的強調,在Java中引入閉包的問題需要重新考慮(BGGA提出的方式確實不好)。至少閉包的缺乏使得用Java做任何真正的函數式編程都是不可能的。
2.缺少壹級功能:這個問題和上壹個有關系,但我覺得更嚴重。在Java中,要達到類似的效果,唯壹的方法就是使用著名的、醜陋的、悲劇的single方法來匿名內部類,但這似乎是壹個很差的方法。即使在C#中,它也通過代理機制提供了更好的實現。
3.原始類型:如果在Java中壹切都是對象該有多完美,但他們就是不這麽設計。所以這就導致了壹些問題,比如妳不能把壹個int放入壹個集合中,這個問題是通過Java5中的自動裝箱特性解決的(下面會提到)。這也造成了傳遞值和引用的麻煩。原生類型數據通過值傳遞給方法(復制壹個副本,然後將其傳遞給函數),而真實對象被傳遞,因此它也應該通過值傳遞,但效果類似於傳遞引用,因為對象可以通過函數內的這個對象地址來訪問。
4.自動裝箱和自動取消裝箱:這個特性是在Java5中引入的,目的是解決由於本地類型的存在而導致的問題。它允許靜默地將本機類型轉換為相應的對象,但這通常會導致其他問題。比如Integer可以為null,int不能,所以JVM只能拋出壹個很難調試的NullPointerException。此外,還可能導致其他奇怪的行為,比如下面這個例子,讓我們很難理解為什麽變量檢驗是假的:
Intger a =新整數(1024);
Intger b =新整數(1024);
布爾測試= a & ltb | | a = = b | | a & gtb;
5.缺少對範例的分類:範例是Java5推出的壹個很酷的特性,但是為了保持與舊版本Java的兼容性,缺少了壹些重要的特性,尤其是在運行時無法體現範例的類型。例如,您有壹個接受列表參數的方法,但是如果傳入壹個列表,您就無法知道操作中範式的確切類型。同樣,妳不能創建壹個規範的數組。這意味著盡管下面的代碼看起來很自然,但它不能被編譯:
List[] listsOfStrings =新列表[3];
6.不可避免的範式警告:妳有沒有發現自己陷入了無法擺脫的範式警告?如果妳像我壹樣經常使用範例,我敢打賭妳有。事實上,正是這個問題的尺度癥狀讓他們認為有必要引入壹個特定的註釋(@SuppressWarnings("unchecked "))來處理這種情況。我認為範例應該設計得更好。
7.不能將void傳遞給方法調用:不得不承認,這種需要將void傳遞給方法的做法,乍壹看有點怪異。我喜歡DSL。當我實現自己的DSL庫(lambdaj)的壹個特定特性時,我必須聲明壹個方法作為這樣的簽名:Void do something(object parameter),其中為這個方法傳入的參數是另壹個方法調用的結果,它唯壹的目的是註冊被調用的對象本身,以便以後執行。令我驚訝的是,即使println方法返回void,似乎也沒有什麽好的理由不允許我這樣寫代碼:
do something(system . out . println(" test "));
8.沒有原生代理機制:代理是壹種非常有效且廣泛使用的模式,但是Java提供的代理機制只是針對接口,而不是具體的類。這也是為什麽提供這種機制的庫,比如cblib,被那麽多主流框架采用,比如Spring和Hibernate。此外,因為cglib是通過在運行時創建委托類的子類來實現的,所以這些方法有壹個眾所周知的限制——不能委托最終類,比如String。
9.壞開關...案例陳述:Java規定開關...case只能選擇int和enum(從Java 5開始)。與Scala等更現代的語言相比,這似乎太弱了。
10,Checked exception:與native類型類似,Checked Exception也成為了Java中的罪惡之源。它迫使程序員做下面兩件非常糟糕和煩人的事情之壹:用大量的嘗試淹沒妳的代碼...捕捉不好、難讀、容易出錯的語句,這樣做最大的意義只是把捕捉到的異常打包成運行時異常,然後再拋出;或者讓大量拋出的聲明子句汙染妳的API,使接口缺乏靈活性和擴展性。
真正的問題是,我在這裏提到的這些主要問題的唯壹解決方案是做出痛苦的選擇,定義壹套新的語言規範並放開當前版本的向後兼容性。我猜想他們永遠不會這樣做,盡管我相信,編寫壹個能夠自動轉換舊Java源代碼並使它們與假定的新版本兼容的程序並不是很難。最後,這也是我決定開始尋找更好的JVM兼容語言的原因。