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