學Java也有段時間了,從Python切換到Java還是有些不適應,會很自然的對兩者進行對比。Java是靜態語言,相比動態語言,它有利有弊。親近了機器語言,遠離了人類語言。
利:更適合機器的語言,因為編譯成了字節碼,所以運行速度比動態語言快
弊:對人類來說,可讀性遠不如動態語言。語法太多,復雜。相對Python,語法復雜度增加了不止一倍
從機器語言到人類語言,中間就是編程語言,一個編程語言越接近機器語言,在機器上的執行速度越快,但可讀性越差;反之,越接近人類語言,在機器上的執行速度越慢,但可讀性越好。
世界上沒有完美的東西,Java也不例外,從開發出來到現在,Java一直在完善自己。但還是有一些地方不盡如人意。
我十分喜歡Apple的產品設計理念:精簡。但Java的設計,跟精簡還有相當的距離。跟Python相比,差距也很明顯。當然,這跟Java是編譯型語言以及直接從C++進化過來有關系。
1. 不支持override靜態字段和靜態方法
override靜態字段,我感覺這個需求非常常見。在父類中定義static字段和static方法,子類調用父類的static方法,但我不想使用父類static字段的默認值,而是想在子類中重新賦值,同時,又不想影響父類的static字段。但Java就是不支持,這點太坑了。
后來,我在Quora(連這個網站也牆,垃圾)上找到了答案:Why can't static methods be overridden? ,里面提到,實例方法的查找是運行時確定的,而類方法和類變量的查找是編譯時確定的,所以不能override。像Smalltalk和Objective-C的類方法的查找是運行時確定的,可以override
2. 接口
接口其實是抽象類的簡化。Java設計者不想用C++的多繼承,所以用的單繼承,但同時增加了接口概念去實現與多繼承相同的功能。不過Java8又往接口里加default方法,導致接口與抽象類之間只剩下一層內褲了:實例字段。那是不是就沒必要定義接口這個概念呢?其實還是有意義的,它相當於Mixin類,相當於在語言層次,強制用戶在多繼承時,必須實現Mixin方式。
3. 沒有函數概念
Java8增加lambda,開始支持匿名函數。但是仍然不支持非匿名函數。如果用戶想定義一個函數,只能用lambda或者用接口實現,這類接口美其名曰:函數接口。這樣設計不好,給函數套了個沒用的套子。
4. 構造方法無法繼承
由於構造方法與類名相同,導致子類無法天然繼承父類的構造方法。定義子類時,必須再定義其構造方法,蛋疼。而Python中,構造方法名稱是固定的`__init__`,子類天然就繼承,非常方便
5. 定義了太多概念,很多沒什么用
POJO,IoC,Model, Entity,DAO, Mapper 一堆概念,增加了開發者的學習成本,但有些沒什么用。比中DAO,Mapper完全是一個東西,IoC其實就是DI
6. 編譯語言的優點
跟腳本語言Python相比,Java的優勢是執行速度快,因為很多都在編譯時進行了優化,即用編譯時間縮短了執行時間。另外,編譯語言要顯式定義類型,才能使用,這樣的好處很多。其中一個是當函數的函數體很長時,你只看簽名就知道這個方法的參數的類型和返回值的類型。類型就是結構,你一眼就知道它的輸入參數的結構和輸出參數的結構,可讀性非常強。而Python這種腳本語言,你只能一行行閱讀源碼才能知道它的入參類型,出參類型。當然,也可以加注釋說明,但可讀性仍遠不如編譯型語言。
當然,這帶來一定的復雜度,Python語言的學習成本比較低,而Java要高很多。相同的功能,Java的代碼量比Python也多出不少。
