日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JAVA之编译期和运行期区别

發(fā)布時(shí)間:2025/3/12 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JAVA之编译期和运行期区别 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

編譯期:檢查是否有語法錯(cuò)誤,如果沒有就將其翻譯成字節(jié)碼文件。即.class文件。
運(yùn)行期:java虛擬機(jī)分配內(nèi)存,解釋執(zhí)行字節(jié)碼文件。

從以下代碼開始說明,歡迎大家指正

可以思考下,第一行跟第二行在編譯時(shí)期有什么區(qū)別?

java編譯時(shí)會(huì)做一些優(yōu)化操作。第一行,因?yàn)槭莾蓚€(gè)常量做運(yùn)算,那么他們的結(jié)果就是確定的,即num1的值是確定的。所以在編譯時(shí),編譯器就會(huì)直接算出num1的值。第二行則不會(huì),java在運(yùn)行時(shí)期才為變量分配內(nèi)存空間。

所以Eclipse編譯得到.class文件,打開class反編譯后可以得到如下代碼:

PS:使用Android Studio 編譯器結(jié)果有點(diǎn)不一樣,但不影響說明。

1、方法重載是在編譯時(shí)執(zhí)行的。因?yàn)樵诰幾g的時(shí)候,如果調(diào)用了一個(gè)重載的方法,那么編譯時(shí)必須確定他調(diào)用的方法是哪個(gè)。如:當(dāng)調(diào)用evaluate(“hello”)時(shí)候,我們?cè)诰幾g時(shí)就可以確定他調(diào)用的method #1.

2、方法的重寫是在運(yùn)行時(shí)進(jìn)行的。這個(gè)也常被稱為運(yùn)行時(shí)多態(tài)的體現(xiàn)。編譯器是沒有辦法知道它調(diào)用的到底是那個(gè)方法,相反的,只有在jvm執(zhí)行過程中,才知曉到底是父子類中的哪個(gè)方法被調(diào)用了。如下:

試想,當(dāng)有如下一個(gè)接口的時(shí)候,我們是無法確定到底是調(diào)用父類還是子類的方法

3、泛型(類型檢測(cè)),這個(gè)發(fā)生在編譯時(shí)。
這也正是泛型的好處之一,可以提前暴露問題,而不是等到運(yùn)行時(shí)出現(xiàn)ClassCastException。編譯器會(huì)在編譯時(shí)對(duì)泛型類型進(jìn)行檢測(cè),并把它重寫成實(shí)際的對(duì)象類型(非泛型代碼),這樣就可以被JVM執(zhí)行了。這個(gè)過程被稱為"類型擦除"。

類型擦除的關(guān)鍵在于從泛型類型中清除類型參數(shù)的相關(guān)信息,并且再必要的時(shí)候添加類型檢查和類型轉(zhuǎn)換的方法。
類型擦除可以簡(jiǎn)單的理解為將泛型java代碼轉(zhuǎn)換為普通java代碼,只不過編譯器更直接點(diǎn),將泛型java代碼直接轉(zhuǎn)換成普通java字節(jié)碼。類型擦除的主要過程如下:
1). 將所有的泛型參數(shù)用其最左邊界(最頂級(jí)的父類型)類型替換。
2). 移除所有的類型參數(shù)。

4. 注解。注解即有可能是運(yùn)行時(shí)也有可能是編譯時(shí)。
如java中的@Override注解就是典型的編譯時(shí)注解,他會(huì)在編譯時(shí)會(huì)檢查一些簡(jiǎn)單的如拼寫的錯(cuò)誤(與父類方法不相同)等
同樣的@Test注解是junit框架的注解,他是一個(gè)運(yùn)行時(shí)注解,他可以在運(yùn)行時(shí)動(dòng)態(tài)的配置相關(guān)信息如timeout等。

5. 異常。異常即有可能是運(yùn)行時(shí)異常,也有可能是編譯時(shí)異常。
RuntimeException是一個(gè)用于指示編譯器不需要檢查的異常。RuntimeException 是在jvm運(yùn)行過程中拋出異常的父類。對(duì)于運(yùn)行時(shí)異常是不需要再方法中顯示的捕獲或者處理的,如NullPointerException,ArrayIndexOutOfBoundsException
已檢查的異常是被編譯器在編譯時(shí)候已經(jīng)檢查過的異常,這些異常需要在try/catch塊中處理的異常。

6. AOP. Aspects能夠在編譯時(shí),預(yù)編譯時(shí)以及運(yùn)行時(shí)使用。
1). 編譯時(shí):當(dāng)你擁有源碼的時(shí)候,AOP編譯器(AspectJ編譯器)能夠編譯源碼并生成編織后的class。這些編織進(jìn)入的額外功能是在編譯時(shí)放進(jìn)去的。
2). 預(yù)編譯時(shí):織入過程有時(shí)候也叫二進(jìn)制織入,它是用來織入到哪些已經(jīng)存在的class文件或者jar中的。
3). 運(yùn)行時(shí):當(dāng)被織入的對(duì)象已經(jīng)被加載如jvm中后,可以動(dòng)態(tài)的織入到這些類中一些信息。

7、繼承:繼承是編譯時(shí)執(zhí)行的,它是靜態(tài)的。這個(gè)過程編譯后就已經(jīng)確定

8、代理(delegate):也稱動(dòng)態(tài)代理,是在運(yùn)行時(shí)執(zhí)行。

如何理解"組合優(yōu)于繼承"這句話?
繼承是一個(gè)多態(tài)的工具,而非重用工具。在沒有多態(tài)關(guān)聯(lián)關(guān)系的對(duì)象間,一些程序員傾向于使用繼承來保持重用。但事實(shí)是,只有當(dāng)子類和父類的關(guān)系為"is a"的關(guān)系時(shí)候,繼承才會(huì)使用。

  • 不要使用繼承來實(shí)現(xiàn)代碼的重用。如果兩者之間沒有"is a"的關(guān)系,那么使用組合來實(shí)現(xiàn)重用。當(dāng)父類的某個(gè)方法修改后,子類的相關(guān)實(shí)現(xiàn)也有可能會(huì)被更改。
  • 不要為了多態(tài)而使用繼承。如果你只是為了實(shí)現(xiàn)多態(tài)而采用繼承模式,那么實(shí)際上組合模式更加適合你,而且更加簡(jiǎn)潔和靈活。
    這也就是為什么GoF設(shè)計(jì)模式中常說"組合優(yōu)于繼承"的原因。
  • 你能區(qū)分編譯時(shí)繼承和運(yùn)行時(shí)繼承的區(qū)別嗎?請(qǐng)列舉例子說明
    實(shí)際上在java中只支持編譯時(shí)繼承。java語言原生是不支持運(yùn)行時(shí)時(shí)繼承的。一般情況下所謂編譯時(shí)繼承如下:
    如上有兩個(gè)類,其中Child為Parent的子類。當(dāng)我們創(chuàng)建一個(gè)Parent實(shí)例的時(shí)候(無論實(shí)際對(duì)象為Parent還是Child),編譯器在編譯期間會(huì)將其替換成實(shí)際類型。所以繼承實(shí)際上在編譯時(shí)就已經(jīng)確定了。

    而在java中,可以設(shè)計(jì)通過組合模式來嘗試模擬下所謂的運(yùn)行時(shí)繼承。

    在Child類中,其中有一個(gè)Parent實(shí)例。通過這種方式,我們動(dòng)態(tài)的child類中代理了parent的相關(guān)功能。

    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

    總結(jié)

    以上是生活随笔為你收集整理的JAVA之编译期和运行期区别的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。