Java向后不兼容历史的观察
在大多數情況下,Java是一個非常向后兼容的編程語言。 這樣做的好處是,與大規模破壞兼容性相比,大型系統通常可以相對容易的方式升級為使用Java的較新版本。 這樣做的主要缺點是Java堅持了一些設計決策,這些決策自那時以來就被認為比理想情況要差,但必須保留在適當的位置以保持一般的向后兼容性。 即使Java與向后兼容性有相當強的聯系,但Java的每個主要版本中仍然存在差異,這些差異可能會在升級基于Java的應用程序時破壞它們。 這些可能發生的中斷(最常見于“拐角事件”中)是本文的主題。
Sun Microsystems和Oracle提供了與Java升級相關的兼容性問題的相當詳細的概述。 我的觀點不是要涵蓋所有版??本中的所有這些問題,而是要強調隨Java的每個主要發行版引入的一些關鍵的不兼容問題,這些問題要么對我個人產生影響,要么對其他人產生更大影響。 這篇文章底部的鏈接提供給Sun / Oracle Java版本的兼容性文檔,以幫助那些尋求更大范圍的讀者。
升級
事后看來,Java的這一早期發行版修復了實現與規范的一些不兼容性也就不足為奇了。 例如, JDK 1.2兼容性參考指出,在1.1版本中實現的String哈希函數與Java語言規范第一版中指定的函數不匹配,并且實際上是無法實現的。” 它補充說,“已實現的函數在某些類別的字符串上執行得非常差”,并解釋說,實現了“ 1.2版中新的String哈希函數”是為了“使實現與規范保持一致并解決性能問題。” 盡管可以預料到對String.hashCode()的更改不會影響大多數應用程序,但是,人們公認“具有依賴于實際String哈希值的持久性數據的應用程序……在理論上可能會受到影響。” 提醒您,依賴對象的hashCode()方法返回特定代碼通常不是一個好主意。
升級
JDK 1.3兼容性參考提到了一些更改,這些更改帶來了更多與JDK規范的實現一致性。 這樣的一個例子是引入了“類型和子包之間的名稱沖突”的更改:
根據…Java語言規范,…包中包含類或接口類型以及具有相同名稱的子包是非法的。 在1.3版之前,幾乎從未執行過此規則。 現在,新的編譯器將一致地執行此規則。 如果在類路徑或源路徑上可以訪問相應的目錄,源文件或類文件,則不管其內容如何,??都可以認為包,類或接口存在。
JDK 1.3還對“方法java.lang.Double.hashcode的實現”進行了更改。
升級
由于JDK 1.4的更改,我在一個項目上遷移到JDK 1.4的升級工作最終花費了比估計更多的時間,因此“編譯器現在拒絕從未命名空間中導入類型的導入語句。” 換句話說,JDK 1.4取消了導入沒有顯式包定義的類的功能。 我們沒有意識到這對我們來說是個問題,因為它所影響的代碼是由第三方工具生成的代碼。 我們沒有控制代碼的生成以強制生成的類位于命名包中,因此它們自動成為“未命名名稱空間”的一部分。 這意味著,使用JDK 1.4,我們將無法再將這些生成的類與我們自己的源代碼一起編譯 。 發現并解決此更改花費的時間比我們預期的要長,或者我們認為這將是相對簡單的JDK版本升級。 當一個人控制代碼時,同一JDK 1.4兼容性參考也指出了最合適的解決方案:“將所有類從未命名的名稱空間移到命名的名稱空間。”
升級
我在上一篇文章“ 關于避免對toString()Result進行語法分析或基于邏輯的美德”中寫過Java SE 5對BigDecimal.toString()的更改。 Java SE 5兼容性參考只是指出:“ J2SE 5.0 BigDecimal的toString()方法的行為與早期版本不同。”
升級到Java SE 6時,最讓我困擾的問題是JDK 6中包含JAXB 。 Java SE 6兼容性參考中未列出此問題,因為此問題的性質在技術上不符合此處記錄的兼容性問題的定義。 但是,在遷移到Java SE 6之前使用單獨下載的JAXB JAR的任何人都可能遇到我遇到的類加載器問題 。 我們大多數人過去用來解決此問題的解決方案是將首選的JAXB JAR放置在指定的目錄中,該目錄是Java認可的標準替代機制 ( 從Java 8開始不推薦使用,并在Java 9中刪除 )的一部分。
升級
升級到Java 7時, com.sun.image.codec.jpeg軟件包的任何使用都被破壞。Java 7兼容性參考指出,“ com.sun.image.codec.jpeg軟件包已在JDK 1.2中添加(1998年12月)。作為控制JPEG格式圖像文件的加載和保存的非標準方式 。 該軟件包從不屬于平臺規范的一部分,已從Java SE 7發行版中刪除。 Java Image I / O API作為標準API被添加到JDK 1.4版本中,從而不再需要com.sun.image.codec.jpeg package 。”
Java 7中重新引入的另一個不兼容性實際上是使實現更好地符合規范的另一個示例。 在這種情況下,在Java SE 6中,具有基本相同的已刪除簽名但具有不同返回類型的方法被視為兩種不同的方法。 這不符合規范,Java 7對此進行了修復。 有關此問題的更多詳細信息,請參見我的博客文章NetBeans 7.1的Internal Compiler和JDK 6尊重方法重載的返回類型以及Java 7兼容性參考中 “摘要”標題下的內容:類無法定義相同擦除的兩個方法簽名,但有兩種不同的返回類型”和“編譯器不允許使用具有相同擦除簽名的非重寫方法”。
Java 7升級也為Substance用戶帶來了一些困難。 非實質性6.2版本的帖子指出:“ Java 7修復– Java的顏色選擇器中的一個錯誤修復破壞了6.1的實質。 這個問題在Substance 6.2中已修復,因此現在應該可以在Java 7上運行!” 破壞Substance的JDK 7更改記錄在各個地方,包括具有Substance外觀的JColorChooser,Java 7 , ColorChooser在具有JDK7的JSlider中導致NullPointerException以及顏色選擇器setColor在Java 7中不起作用 。
升級
就像Java 7的更改影響了實質性的一樣,Java 8帶來的更改也直接影響了幾個流行且廣泛使用的Java庫。 盡管此更改可能直接影響了相對較少的Java應用程序,但它間接地有可能影響許多Java應用程序。 幸運的是,這些Java庫的維護人員傾向于快速解決此問題。 這是另一個實施規范的例子,該規范被嚴格化(更正)并破壞基于無法正確實施規范的實現而起作用的事物。 在這種情況下,更改/更正在字節碼驗證程序中。 《 JDK 8兼容性指南》指出:“當指令引用實例初始化方法(“ <init> ”)時,invokespecial指令的驗證已加強。 Niv Steingarten的博客文章Oracle最新的Java 8更新破壞了您的工具—它是如何發生的?
升級
Java 9似乎可能會引入一些重要的向后兼容性問題 ,尤其是考慮到模塊化的引入。 盡管這些破損是什么尚待觀察,但最初提議取消對sun.misc.Unsafe的訪問已經引起了軒然大波 。 這是另一個示例,其中官方不支持的API可能不會被大多數應用程序直接使用,而可能被眾多應用程序間接使用 ,因為它們依賴的庫和產品都在使用它。 有趣的是,這引起了Mark Reinhold的提議 ,即將內部API封裝在JDK 9中。考慮到與主要Java版本之間刪除和更改的內部API相關的眾多兼容性問題,這似乎是個好主意。
- 避免利用違反規范的不正確實現,因為在更改實現以強制執行規范時,實現中的漏洞利用可能根本不起作用。
- 當心并謹慎使用任何宣傳為實驗性的或在將來的Java版本中可能刪除的API,類和工具。 這包括sun。*軟件包以及不建議使用的工具和API。
- 我喜歡建議的“將內部API封裝在JDK 9中”的JDK 9方法來解決主要版本升級中的這些常見問題。
- 不要依賴 toString()實現返回的String來實現程序邏輯。
結論
多年來,人們為保持Java在很大程度上向后兼容一直付出了巨大的努力。 但是,在某些情況下不能保持這種向后兼容性。 我在這篇文章中查看了一些示例,并從這些示例中提取了一些觀察和教訓。 當開發人員避免使用已棄用的功能,避免使用實驗性功能以及避免使用非標準功能時,向Java新版本的遷移往往會更容易。 同樣,某些編碼實踐(例如避免將邏輯基于toString()結果)也可以提供幫助。
資源
- Oracle / Sun Java版本兼容性指南(按相反順序)
- JDK 8兼容性指南
- 其他相關資源
- 升級主要Java版本(7至8)
翻譯自: https://www.javacodegeeks.com/2016/06/observations-history-java-backwards-incompatibility.html
總結
以上是生活随笔為你收集整理的Java向后不兼容历史的观察的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 世界上最富有的家族(世界十大最有钱的家族
- 下一篇: 怎么连接路由器如何教接路由器