臭名昭著的Java错误和陷阱
在2000年,我上大學,瀕臨選擇一種語言來發展自己的職業。 Java尚未成為主流,但很受人們歡迎。 與靜態html頁面相比,小應用程序(尚未破碎)花哨且富有光澤。 Swing不是構建桌面應用程序的不錯選擇。 J2EE越來越受到關注。 從那時起已經過去了13年,盡管小程序失敗了,Java成為主流,盡管對于小應用程序而言,它并沒有真正考慮到這一點,而且J2EE太復雜了,甚至無法構建簡單的東西,但是仍然沒有什么阻止Java成為最受歡迎的編程語言。
毫不奇怪,Java非常漂亮,類型安全且易于學習。 Java中有很多很好的實現細節,例如垃圾收集器,字符串
(最終類),提供了合并和快速排序的出色實現的集合,內置在哈希碼方法中的等等。 但是,Java仍然遠非完美,可能會引入一些意想不到的行為。
Abs錯誤:
好吧,這是一個非常小的缺陷,但是Math.abs()函數可能會返回負值。 奇怪的? 實際上很簡單,Java整數可以得到-2,147,483,648到2,147,483,647之間的值,這清楚地表明-2,147,483,648不能以正數表示。
那是一個錯誤嗎? 好吧,期望值是正的,所以可以肯定,但是最終這實際上是一個溢出。 那么如何解決呢? 一種方法是在使用abs函數或使用位運算符代替之前操縱Integer.MIN_VALUE。
自動裝箱基元陷阱:
通過自動裝箱,可以輕松地使用基本類型及其對象對應物。 但是,在它們之間移動可能會導致某些意外行為。 例如,不能使用==運算符將Integer i1 = 6與Integer i2 = 6進行比較,其中可以將int i3 = 6與具有==的整數進行比較。 但是,使用equals可能也無法按預期工作。 例如Long x = 0L; 當x.equals(0L)返回true,而當x.equals(0)返回false。 奇怪的? 并非如此,因為x很長,其中0(沒有L)是int。 因此,它們甚至不是相同的對象類型。 還將原始類型與集合一起使用可能會導致意外行為。 最后,自動裝箱可能會導致過載問題。 假設我們有Integer i = 6并調用方法sum(i); 我們有兩種求和方法,例如; sum(long val)和sum(Long val)。 您認為會叫哪一個? 還是合理的,但不希望乍一看,可能會導致應用程序出現問題。
BigDecimal構造函數錯誤:
如果您尚未查看Joshua Bloch的Java Puzzlers 。 如果使用雙精度構造函數創建兩個大十進制數(x1 = new BigDecimal(2.00)和x2 = new BigDecimal(1.10)),然后使用減法(x1.subtract(x2)),則最終結果為0.8999999999。 BigDecimal的double構造函數無法按預期工作,而需要使用字符串構造函數(新的BigDecimal(“ 2.00”))。 這可能是一個嚴重的問題,因為BigDecimal被廣泛用于金錢計算!
System.out.println陷阱:
println()是對CS學生更難的第一個函數。 它很容易并且經常使用。 當您嘗試某些邏輯或調試某些值時,通常可以使用。 但是System.out是同步的,因此在訪問時會獲取一個鎖。 因此,使用println可能會使您的應用程序在同步上下文中運行,這實際上意味著訪問println時線程將被阻塞。 想象一下使用println的Web服務器和應用程序日志記錄,您最終將獲得線程鎖,并且每個請求都在等待其他請求。 因此,println可以而且有用,但不適用于實際的應用程序和日志記錄!
地圖錯誤:
再次看一下Joshua Bloch的Java Puzzlers ,第五個難題(大小很重要)在HashMap和EnumMap之間引入了一種奇怪的行為,其中具有相同的值,一個地圖的大小為2,另一個地圖的大小為1。作為IdentityHashMap,EnumMap可能會引入此行為。
這是錯誤嗎? 可以肯定的是,我們期望地圖實現中具有相同的原理,但是Bloch描述了這一點,因為當時的規范尚不清楚。
CPU編號錯誤:
除非您真的依賴硬件,否則這可能不是一個大問題。 為了獲得可用處理器數,Java提供了Runtime.getRuntime()。availableProcessors()方法,該方法返回一個int數作為可用處理器數。 但是,如果嘗試一下,最終可能會得到意外的數字。 例如,在我的四核i7上,我得到8。因此,此方法不返回硬件cpus數量,也不是核心數量,而是返回執行引擎(虛擬核心)數量。 就我而言,因為四核i7支持超踩,所以實際上它就像擁有八核。
那是一個錯誤嗎? 絕對不是,因為硬件和操作系統的運行方式就好像它們具有的物理CPU數量一樣,但是如果您依靠可靠的硬件,仍然要小心。
通用數組
在Java中,創建數組的方式如下:int [] arr = new int [5]; 因此,如果您具有T的通用類型,則希望以這種方式創建通用數組:T [] = new T [5]; 但根本不能。 Java不允許創建泛型數組,這實際上是因為泛型是使用Erasure在Java中實現的。 泛型僅在編譯器級別實現,實際上每個類僅生成一個類文件。 因此,要創建數組,我們需要進行如下丑陋的轉換:T [] =(T [])new Object [5]; 當您嘗試編譯時,編譯器會發出警告,提示您正在進行不安全的轉換!
當然,這不是錯誤,它只是在實現泛型時為了簡化和兼容性而給出的實現問題。 但是在設計問題上發出編譯器警告可能會使第一次遇到該問題的人感到困惑。 因此,這絕對不是清單的結尾,但是Java仍然提供了漂亮的語法,類型安全性和易于實現的易于學習的語言。 最后,沒有語言或實現是完美的!
翻譯自: https://www.javacodegeeks.com/2013/04/infamous-java-bugs-and-pitfalls.html
總結
以上是生活随笔為你收集整理的臭名昭著的Java错误和陷阱的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小米电视机评测(小米电视啥样)
- 下一篇: 松下gx9微单相机怎么样