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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JAVA之编译期和运行期区别

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

編譯期:檢查是否有語法錯誤,如果沒有就將其翻譯成字節碼文件。即.class文件。
運行期:java虛擬機分配內存,解釋執行字節碼文件。

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

可以思考下,第一行跟第二行在編譯時期有什么區別?

java編譯時會做一些優化操作。第一行,因為是兩個常量做運算,那么他們的結果就是確定的,即num1的值是確定的。所以在編譯時,編譯器就會直接算出num1的值。第二行則不會,java在運行時期才為變量分配內存空間。

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

PS:使用Android Studio 編譯器結果有點不一樣,但不影響說明。

1、方法重載是在編譯時執行的。因為在編譯的時候,如果調用了一個重載的方法,那么編譯時必須確定他調用的方法是哪個。如:當調用evaluate(“hello”)時候,我們在編譯時就可以確定他調用的method #1.

2、方法的重寫是在運行時進行的。這個也常被稱為運行時多態的體現。編譯器是沒有辦法知道它調用的到底是那個方法,相反的,只有在jvm執行過程中,才知曉到底是父子類中的哪個方法被調用了。如下:

試想,當有如下一個接口的時候,我們是無法確定到底是調用父類還是子類的方法

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

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

4. 注解。注解即有可能是運行時也有可能是編譯時。
如java中的@Override注解就是典型的編譯時注解,他會在編譯時會檢查一些簡單的如拼寫的錯誤(與父類方法不相同)等
同樣的@Test注解是junit框架的注解,他是一個運行時注解,他可以在運行時動態的配置相關信息如timeout等。

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

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

7、繼承:繼承是編譯時執行的,它是靜態的。這個過程編譯后就已經確定

8、代理(delegate):也稱動態代理,是在運行時執行。

如何理解"組合優于繼承"這句話?
繼承是一個多態的工具,而非重用工具。在沒有多態關聯關系的對象間,一些程序員傾向于使用繼承來保持重用。但事實是,只有當子類和父類的關系為"is a"的關系時候,繼承才會使用。

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

    而在java中,可以設計通過組合模式來嘗試模擬下所謂的運行時繼承。

    在Child類中,其中有一個Parent實例。通過這種方式,我們動態的child類中代理了parent的相關功能。

    創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

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

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。