強/弱類型、動/靜類型、GC 和 VM,你真的分清楚了麼?
強類型 Vs. 弱類型
- 強和弱是一個相對的概念,強是指傾向於將未定義的行爲視做錯誤(Java、Python),弱是指傾向於進行隱式的轉換、忽略類型相關的錯誤(JavaScript)。
- 不少設計得不夠嚴謹的語言,雖然大多數狀況下(或者咱們一般鼓勵你們這麼作)是強類型的,但也有弱類型的部分(PHP)
- 還有的語言由於提供的抽象能力很弱,咱們不得不去用弱類型的部分(C)
- 鴨子類型(duck typing)是強弱類型的一個折中(常見於動態類型中,例如 Python),兼顧了靈活性和嚴謹性。
- 咱們認爲弱類型是爲了方便,而強類型是爲了儘早發現錯誤。
動態類型 Vs. 靜態類型
- 靜態類型的變量的類型是在編譯時肯定的(C++、Java);動態類型的類型是在運行時肯定的(JavaScript、Python),例如你能夠在一個 if 的兩個分支裏給一個變量賦值不一樣的類型。
- 有的動態類型語言也會添加編譯期的類型檢查(TypeScript、Python),但由於語言自己的動態性,這些檢查僅能覆蓋一部分狀況。
- 在動態類型的語言中由於類型不那麼重要,因此不少時候甚至沒有提供指定類型的語法(隱含了運行時的自動推導);而在靜態類型語言裏一般須要爲變量指定類型,因此纔有了編譯期自動類型推導來提供便利,而動態類型語言則作不到這一點(由於不能在編譯期肯定類型,更無從推導)。
- 咱們認爲靜態類型有助於在編譯時發現有關類型的錯誤,肯定的類型也給了編譯期更多的優化空間;而動態類型給了開發者更高的靈活度。
垃圾回收 Vs. 無垃圾回收
- 無 GC 是指代碼必須自行管理申請到的內存並在恰當的時機釋放(Rust、C/C++);而有 GC 的語言會經過引用計數(PHP<5.3)、標記複製(V8)等方式按期查找無用的內存進行釋放。
- 標記複製的 GC 的過程一般會引發線程的暫停,也會花費額外的 CPU;但 GC 對於創建高層次的抽象又是必不可少的:異常、閉包等(雖然 C++ 在無 GC 的狀況下也實現了這兩個特性,但也引入了很是高的複雜度)。
- 咱們認爲有 GC 能夠簡化對內存的管理,創建複雜的抽象;而無 GC 能夠獲得更底層的對內存的控制,帶來更好的性能,避免由於 GC 形成的卡頓。
虛擬機 VS. 本地代碼
- 虛擬機是指在語言和 CPU 之間還有一個用於進行翻譯的層次(JavaScript、Java);無虛擬機是指編譯器直接生成本地代碼給 CPU 執行(C/C++、Golang)。
- 虛擬機也提供了更爲複雜的運行時的動態特性,但這些特性有的時候也能夠在沒有虛擬機的狀況下實現(例如 C++ 的運行時類型識別、Go 的 GC)。
- 虛擬機能夠以解釋的方式執行(Python,將代碼視做一種數據指令來執行),也能夠即時編譯(JIT)的方式來執行(V8,先將代碼編譯到本地代碼而後執行),有時也會混合這兩種方式(爲了更快的啓動速度)。
- 咱們認爲無虛擬機的語言能夠在更低的層次和其餘程序交互,同時也自然地有着更好的性能;而有虛擬機的語言則能夠輕鬆地跨平臺,針對特定的架構在運行時即時編譯出更高性能的代碼。
小結
語言 |
強類型 |
動態類型 |
垃圾回收 |
虛擬機 |
C |
|
|
|
|
C++ |
Y |
|
|
|
Java |
Y |
|
Y |
Y |
Python |
Y |
Y |
Y |
Y |
JavaScript |
|
Y |
Y |
Y |
PHP |
|
Y |
Y |
Y |
Golang |
Y |
|
Y |
|
Rust |
Y |
|
|
|
參考來源:閉包
歡迎關注本站公眾號,獲取更多信息