日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
小心陷阱!Java中常犯的10個(gè)錯(cuò)誤

本文轉(zhuǎn)載自公眾號(hào)“讀芯術(shù)”(ID:AI_Discovery)

常在河邊走哪有不濕鞋,有些錯(cuò)誤真的是防不勝防。然而,以筆者面試過(guò)從菜鳥(niǎo)到高級(jí)技術(shù)負(fù)責(zé)人,幾十位軟件工程師的經(jīng)歷看來(lái),在更多情況下,候選人在對(duì)基本概念的掌握上是存在差距的。

本文中筆者根據(jù)自己作為技術(shù)主管和面試官的經(jīng)驗(yàn),列出Java開(kāi)發(fā)人員最常犯的錯(cuò)誤,快看看自己是不是中槍了。

1. 忽略訪問(wèn)修飾符

雖然有點(diǎn)莫名其妙,但候選者真的經(jīng)常忘記Java中protected訪問(wèn)修飾符的作用域。也許是因?yàn)槊嬖囘^(guò)程中過(guò)于焦慮和緊張,他們通常只能答出其一:

  • 可從子類訪問(wèn)protected字段、方法和構(gòu)造函數(shù)。
  • 可從同一包中訪問(wèn)protected字段、方法和構(gòu)造函數(shù)。

此外,包的作用域能幫助許多開(kāi)發(fā)人員編寫(xiě)自己的測(cè)試:可以從測(cè)試路徑訪問(wèn)受保護(hù)的方法。所以忘記這個(gè)屬性等同于在面試中表明自己從來(lái)沒(méi)有編寫(xiě)過(guò)測(cè)試!

2. 字符串連接

如果使用大量字符串或大型字符串,則可能會(huì)在連接過(guò)程中浪費(fèi)大量?jī)?nèi)存。

上述示例是創(chuàng)建一些StringBuilder和String對(duì)象:準(zhǔn)確來(lái)說(shuō),是10.000.000個(gè)StringBuilder和10.000.001個(gè)String。

解釋:

先退一步,看看發(fā)生了什么。

當(dāng)使用+運(yùn)算符進(jìn)行字符串連接時(shí),將創(chuàng)建一個(gè)中間對(duì)象,該對(duì)象存儲(chǔ)連接的結(jié)果后,將結(jié)果賦值給目標(biāo)對(duì)象。

在如上示例中,一共創(chuàng)建了3個(gè)對(duì)象:2個(gè)用于文本,1個(gè)用于連接,即第一個(gè)字符串result的副本加上第二個(gè)字符串“world!”。因?yàn)镾tring是不可變的,所以這種字符串連接是可以實(shí)現(xiàn)的。

但是編譯器是足夠智能的,可以將代碼轉(zhuǎn)化為以下內(nèi)容(Java9+不適用,因?yàn)樗褂肧tringContactFacotry,但結(jié)果非常相似):

此優(yōu)化刪除了中間連接對(duì)象,內(nèi)存被2個(gè)字符串文本和1個(gè)StringBuilder占用。總體而言,字符串對(duì)象的數(shù)量從O(n2)下降到O(n)。

回到第一個(gè)示例,編譯器對(duì)代碼的優(yōu)化如下:

編譯器只是優(yōu)化了內(nèi)部連接,但這會(huì)創(chuàng)建很多StringBuilder和String對(duì)象!連接字符串的正確方法如下,只需一個(gè)StringBuilder和一個(gè)String。

3. 沒(méi)有使用equals()

如果你正在使用==(比較運(yùn)算符)而不是調(diào)用equals()函數(shù),那么你需要改變這個(gè)習(xí)慣,結(jié)果可能會(huì)令人大吃一驚。

解釋:

當(dāng)想要比較兩個(gè)String以及其他任何對(duì)象時(shí),不要使用==。==只比較兩個(gè)操作數(shù)的對(duì)象引用(內(nèi)存地址比較)而非內(nèi)容。

在上面的例子中,字符串不能啟動(dòng)字符串駐留機(jī)制:它的內(nèi)存地址與x不同。

4. 返回null

筆者已經(jīng)發(fā)現(xiàn)了很多次這樣的方法:

返回null的問(wèn)題是強(qiáng)行讓調(diào)用方對(duì)結(jié)果進(jìn)行空檢查;在這種情況下,如果沒(méi)有項(xiàng),調(diào)用方就會(huì)返回空列表。

開(kāi)發(fā)人員總是希望返回一個(gè)異?;蛱厥鈱?duì)象(如空列表),否則使用代碼的應(yīng)用程序?qū)⑹艿絅ullPointerException的影響。

5. 密碼為字符串

將用戶提供的密碼存儲(chǔ)在字符串對(duì)象中是一個(gè)安全問(wèn)題,字符串容易受到內(nèi)存攻擊。

應(yīng)該使用char[],就如同JPasswordField和Password4j正在做的那樣。但如果討論的是Web應(yīng)用程序,大多數(shù)Web容器都將HttpServletRequest對(duì)象中的純文本密碼作為String傳遞,所以開(kāi)發(fā)人員幾乎對(duì)此無(wú)能為力。

圖源:unsplash

解釋:

字符串由Java虛擬機(jī)(JVM)(駐留)緩存并存儲(chǔ)在PermGen空間(Java8之前)或堆空間中。在這兩種情況下,只有在垃圾回收發(fā)生后才刪除緩存值:這意味著無(wú)法得知特定值何時(shí)會(huì)從字符串池中刪除,因?yàn)槔占鞯男袨槭遣淮_定的。

另一個(gè)問(wèn)題是,String是不可變的,因此不能清除它們。然而char[]是可變的,并且可以在處理后刪除(例如用0替換每個(gè)元素)。通過(guò)這個(gè)簡(jiǎn)單的技巧,攻擊者只能在內(nèi)存中找到全為零的數(shù)組而不是純文本密碼。

6. 傳遞null

傳遞null意味著,理所當(dāng)然地認(rèn)為調(diào)用的代碼可以管理null。如果不能,那么應(yīng)用程序肯定會(huì)拋出NullPointerException。

另外,顯式傳遞null會(huì)使代碼越來(lái)越混亂。下面是一個(gè)典型實(shí)例:

調(diào)用init()時(shí),沒(méi)有可用的User對(duì)象。那么,如果一個(gè)User都沒(méi)有,為什么要調(diào)用一個(gè)對(duì)User進(jìn)行操作的函數(shù)呢?如果需要grantAccessToUser()中的邏輯,就應(yīng)該從其他的函數(shù)中提取并使用,而非傳遞null。

7. Heavy methods

以下示例可能會(huì)導(dǎo)致系統(tǒng)性能損失:

Pattern.compile()是一個(gè)資源占用極高的函數(shù),不應(yīng)在每次檢查字符串是否與同一模式匹配時(shí)都調(diào)用它。

解釋:

Pattern.compile() 將模式預(yù)編譯,以便使用更快的內(nèi)存表示。與單個(gè)匹配相比,此操作需要極強(qiáng)的計(jì)算能力。

增加性能的經(jīng)典方法是在靜態(tài)字段中緩存Pattern對(duì)象,如下所示:

每次使用同一個(gè)資源占用極高的無(wú)狀態(tài)對(duì)象時(shí),都應(yīng)該使用這個(gè)解決方案。

8. 迭代時(shí)處理集合

這段代碼將拋出ConcurrentModificationException。

解釋:

在迭代時(shí)從列表中刪除某個(gè)項(xiàng)目,列表迭代器會(huì)運(yùn)行不良,例如跳過(guò)元素、重復(fù)元素、索引數(shù)組末尾等。這就是許多集合更容易拋出oncurrentModificationException的原因。

使用底層數(shù)組迭代器:

9. 使用“返回碼”而不是拋出異常

在某種意義上,開(kāi)發(fā)人員認(rèn)為異常是不祥的,因此他們傾向于編寫(xiě)返回奇怪值的函數(shù),如-1或“C_ERR”。

這是一個(gè)值得創(chuàng)建自定義Exception的典型情況。該示例可以改寫(xiě)如下:

正如所見(jiàn),代碼的可讀性和可維護(hù)性大大提高。調(diào)用者只需讀取DeviceStartException的內(nèi)容,而不必處理每個(gè)返回碼。

10. 使用StringBuffer

由于StringBuffer的同步特性,此示例會(huì)產(chǎn)生大量?jī)?nèi)存占用。在更復(fù)雜的環(huán)境中,讀取器可能會(huì)錯(cuò)認(rèn)為某些不必要的同步是必要的。

如果項(xiàng)目中包含StringBuffer,可能是因?yàn)槟承┻z留API(即Java5之前)需要它,而很少是因?yàn)榇a試圖在并發(fā)環(huán)境中追加String。改用StringBuilder:在Java5時(shí)引入,其所有操作是不同步的。

這只是筆者在面試和活動(dòng)項(xiàng)目中看到的部分錯(cuò)誤,還沒(méi)有提到面向?qū)ο缶幊?OOP)的陷阱、設(shè)計(jì)模式、過(guò)度設(shè)計(jì)、內(nèi)存泄漏等缺陷……

圖源:xkcd

如果你有這些問(wèn)題,那么是時(shí)候改變編碼風(fēng)格。這并不難,避免這些陷阱能增強(qiáng)開(kāi)發(fā)人員的經(jīng)驗(yàn),并且使人主動(dòng)為下一次面試做更多的準(zhǔn)備。

多使用像SonarQube這樣的靜態(tài)代碼分析器,它能指出實(shí)際錯(cuò)誤,突顯潛在錯(cuò)誤。

[[322885]]

圖源:unsplash

更重要的是保持學(xué)習(xí),不僅是語(yǔ)法,還包括任何編程語(yǔ)言背后的理論。多敲代碼多練習(xí),讓小錯(cuò)誤遠(yuǎn)離你~


網(wǎng)頁(yè)名稱:小心陷阱!Java中常犯的10個(gè)錯(cuò)誤
文章分享:http://m.5511xx.com/article/cdeidji.html