當你寫Java HelloWorld時候,背後到底發生什麼?
每一個主要學過寫代碼的人,都知道helloworld是做什麼的。而不同的程序與眼中的Helloworld深度和層次是不一樣的,這篇文章讓我們更加深度的解讀一下java的helloworld背後的故事。
1
為什麼java的所有代碼都是在類中?
java的設計邏輯就是基於類來開發,所以所有的方法和類函數都是基於類來彈的。這和c++這門是有本質的區別的。
一定程度上,這樣的設計讓JAVA面向對象的底蘊更加濃厚,所有的事務邏輯都應該是以類的某一個實例來出現。
而面向對象相對於函數式的編程好處,可以說有很多,其中最為重要的則是模塊化和拓展性。
2
為什麼main函數永遠有一個static修飾符?
main函數是程序運行的入口,static修飾符告訴我們,這個函數是屬於類本身的一部分,而不是屬於某一實例。
那為什麼我們一定要用static來作為一個程序入口呢? 可以不用嗎?
如果一個方法不是static的,那這個方法或者這個對象必須是先被創建才能被使用。而作為程序的入口,自然這是不合理的。
就如同生雞生蛋的問題,你什麼都沒有,沒人可以做創建。所以static就是要讓main方法是無需創建而直接可以調用的。
String[ ] args是做什麼用的?
這些就是在命令行調用時候傳入的參數,就如同ls -l -t後面的-l -t這些參數。都是為了初始化時候,將參數輸入程序。
3
HelloWorld的位元組碼長啥樣?
helloworld在執行前,會被編譯成Java的位元組碼存儲在.class文件中。位元組碼本身不可讀,但是我們可以通過hex editor這樣的工具來簡單看到一些內容。
在bytecode前幾個位元組碼里,我們看到CA字元這樣的opcode。這些叫做記憶碼(不知道怎麼翻譯,mnemonic code)。
這些記憶碼是不可讀的,但是我們可以通過javap命令里看看.class文件里的記憶碼。
javap -classpath . -c HelloWorld
javap -c可以列印出程序的彙編代碼,彙編代碼也就是位元組碼的前一個階段。
這段彙編包含兩個方法,一個是默認的構造器,這部分編譯器自己做好的,另一個則是main函數。
在每個方法下面則是一串執行的命令碼,aload_o,invoke這樣的命令。需要知道每個命令的含義,可以看java bytecode list在java的官網上有。
簡單介紹下,aload_o就是從本地變數o載入一個引用到棧上,getstatic則是拿到一個類的static的方法。
那這些彙編左邊的數字是什麼呢?這些命令是存在一個數組中,每個命令佔用的位元組空間不一樣,所以數字就不是連續的。
這個.class文件是如何執行的呢?
在main函數執行之前,JVM需要執行load, link, initialize這些工作。
load: 就是要把class/interface的二進位碼載入到JVM
link: 將這些二進位數據放到JVM的run-time state
initialize: 將變數初始化
所有的工作做完之後,main函數就會被push到JVM棧中,程序計數器會設定到對應位置,開始執行程序。當所有程序執行完,JVM會將Helloworld pop出來,程序結束。
結語
IT是一個相對其他行業更為公平的平台。所謂公平就是,不論長相,不論背景,你的能力決定一切。
廣大的青年才俊們,只要你有真本事,就不用擔心自己在這個行業的前途。
想要系統學習Java知識 加入學習群一四四九零一零七六 可以免費學習java還有大量學習乾貨哦
※解析JavaScript函數的多種寫法
※C語言 代碼之坦克大戰
※web前端和Java學哪個好?哪個就業形勢好
※面試官就問了一個Java問題,幾十號人集體蒙圈?
※怎樣成為一個JavaWeb開發者?
TAG:IT技術java交流 |