學(xué)習(xí)編程的第一課,就是介紹這門編程語言的特點。翻開C語言的教程,你就會在他的特性中發(fā)現(xiàn)這樣一點:擁有很強(qiáng)的可移植性。然后翻開java語言的教程,你也會發(fā)現(xiàn)可移植性高的描述。再多翻幾本手冊,你會發(fā)現(xiàn)可移植性好像是編程語言都具有的一種特性。那么編程語言在提到自身的優(yōu)勢的時候,為什么要把這樣一個近乎人人都有的特性提出來呢?他們之間又有什么差異呢?請聽小編慢慢分解。
編譯&解釋
一門編程語言從源代碼到機(jī)器可執(zhí)行的程序,有兩種方式,一種是編譯,一種是解釋,這并不是對編程語言的一種界定,因為有些語言既可以編譯執(zhí)行也可以解釋執(zhí)行(有種說法是,一些編程語言在開發(fā)的時候使用解釋的方式進(jìn)行調(diào)試,在后期再改成編譯方式執(zhí)行,這樣能快速調(diào)整語言的特性,比如JavaScript的V8引擎就引入了即時編譯功能)。就像作一道菜,源代碼就是菜譜,編譯執(zhí)行就是先將代碼遍掃一遍,然后進(jìn)行執(zhí)行,就像先把菜譜看一遍,學(xué)會了再執(zhí)行;而解釋執(zhí)行是代碼逐行解釋,就像是看菜譜的步驟,一個步驟看一遍,逐步執(zhí)行。理想情況下編譯執(zhí)行和解釋執(zhí)行應(yīng)該是效率相同的,但是解釋執(zhí)行并不能預(yù)測到后面的結(jié)果,所以需要花費(fèi)一些算力去進(jìn)行優(yōu)化(比如有有一個變量,在某處用完后就可以釋放了,在編譯執(zhí)行過程中就可以直接釋放,而解釋執(zhí)行就不能釋放,因為他不知道這個變量后面是否還會使用)。
編譯和解釋的區(qū)別不僅僅在運(yùn)行過程上,在運(yùn)行方式上也有區(qū)別:編譯是將高級語言轉(zhuǎn)化成專屬于目標(biāo)機(jī)器的機(jī)器語言。解釋則是直接執(zhí)行高級語言(執(zhí)行高級語言的過程,是將單行代碼轉(zhuǎn)換為機(jī)器語言的過程)。
可移植性
講了那么多,還是沒有提到可移植性。但實際上,上面的內(nèi)容正是決定可移植性的一個因素。我們知道,編譯過程,是將一門高級語言轉(zhuǎn)化為目標(biāo)機(jī)器語言,而中間需要編譯器的介入。實際上,不同的機(jī)器使用的機(jī)器語言是不同的,所以使用的編譯器也是不同的,高級語言的通用特性,就是高級語言可以通過不同的編譯器轉(zhuǎn)換成不同的機(jī)器語言。雖然最終的編譯結(jié)果不同,但源代碼是相同的,運(yùn)行結(jié)果也是相同的,所以高級語言的源代碼基本都具有代碼可移植性。
而解釋過程就更加厲害了,一門語言要適用于一個平臺,首先要在這個平臺上實現(xiàn)相應(yīng)的解釋器。然后,我們知道,解釋型語言是直接用解釋器執(zhí)行高級語言的,這也就決定了同樣的代碼可以在不同的機(jī)器上運(yùn)行出相同的效果。
另一個因素
實際上上面的內(nèi)容只是一種比較理想的存在,Windows和linux的內(nèi)核是完全不同的,他們能提供的系統(tǒng)操作也是不同的。所以要適配這樣的不同平臺的代碼,實際上還是得進(jìn)行一定的修改。
一處編譯,處處執(zhí)行
還有一種神奇的存在,號稱一處編譯處處執(zhí)行,那就是java。關(guān)于java的一處編譯處處執(zhí)行,可以參考小編的這篇文章:一處編譯處處運(yùn)行如何實現(xiàn)?淺析語言的跨平臺性
java的這個特性,又叫跨平臺可移植性,是一種比較高級的存在。c語言這種編譯型語言和JavaScript這種解釋型語言的優(yōu)點被其融合在一起。java在編譯過程中避免了解釋型語言的一些問題,使最后編譯出來的字節(jié)碼在解釋執(zhí)行的時候盡可能的達(dá)到接近編譯執(zhí)行的速度。而在最后執(zhí)行的過程中使用解釋執(zhí)行,繼承了解釋型語言的跨平臺的優(yōu)點。
由于python有一個版本(JPython)是使用java實現(xiàn)的,這個版本也可以將python編譯成java字節(jié)碼文件,然后再jvm上解釋執(zhí)行,所以JPython也是這樣的高級存在。
小結(jié)
接下來是對本文章的一個總結(jié):
可移植性,是高級語言都有的一個特點,只要具有可移植性,他的源代碼就可以在不同的平臺編譯出相應(yīng)的結(jié)果。
跨平臺性,是解釋型語言的一個特點,只要目標(biāo)平臺擁有對應(yīng)的解釋器,源代碼就可以在這個平臺運(yùn)行出相應(yīng)的結(jié)果。