為什么char數(shù)組比Java中的String更適合存儲(chǔ)密碼?
另一個(gè)基于String的棘手Java問(wèn)題,相信我只有很少的Java程序員可以正確回答這個(gè)問(wèn)題。這是一個(gè)真正艱難的核心Java面試問(wèn)題,并且需要對(duì)String的扎實(shí)知識(shí)才能回答這個(gè)問(wèn)題。
這是最近在Java面試中向我的一位朋友詢問(wèn)的問(wèn)題。他正在接受技術(shù)主管職位的面試,并且有超過(guò)6年的經(jīng)驗(yàn)。如果你還沒(méi)有遇到過(guò)這種情況,那么字符數(shù)組和字符串可以用來(lái)存儲(chǔ)文本數(shù)據(jù),但是選擇一個(gè)而不是另一個(gè)很難。但正如我的朋友所說(shuō),任何與String相關(guān)的問(wèn)題都必須對(duì)字符串的特殊屬性有一些線索,比如不變性,他用它來(lái)說(shuō)服訪提問(wèn)的人。在這里,我們將探討為什么你應(yīng)該使用char[]存儲(chǔ)密碼而不是String的一些原因。
字符串:
1)由于字符串在Java中是不可變的,如果你將密碼存儲(chǔ)為純文本,它將在內(nèi)存中可用,直到垃圾收集器清除它.并且為了可重用性,會(huì)存在String在字符串池中,它很可能會(huì)保留在內(nèi)存中持續(xù)很長(zhǎng)時(shí)間,從而構(gòu)成安全威脅。
由于任何有權(quán)訪問(wèn)內(nèi)存轉(zhuǎn)儲(chǔ)的人都可以以明文形式找到密碼,這是另一個(gè)原因,你應(yīng)該始終使用加密密碼而不是純文本。由于字符串是不可變的,所以不能更改字符串的內(nèi)容,因?yàn)槿魏胃亩紩?huì)產(chǎn)生新的字符串,而如果你使用char[],你就可以將所有元素設(shè)置為空白或零。因此,在字符數(shù)組中存儲(chǔ)密碼可以明顯降低竊取密碼的安全風(fēng)險(xiǎn)。
2)Java本身建議使用JPasswordField的getPassword()方法,該方法返回一個(gè)char[]和不推薦使用的getTex()方法,該方法以明文形式返回密碼,由于安全原因。應(yīng)遵循Java團(tuán)隊(duì)的建議,堅(jiān)持標(biāo)準(zhǔn)而不是反對(duì)它。
3)使用String時(shí),總是存在在日志文件或控制臺(tái)中打印純文本的風(fēng)險(xiǎn),但如果使用Array,則不會(huì)打印數(shù)組的內(nèi)容而是打印其內(nèi)存位置。雖然不是一個(gè)真正的原因,但仍然有道理。
StringstrPassword=“Unknown”;
char[]charPassword=newchar[]{'U','n','k','w','o','n'};
System.out.println(“字符密碼:”+strPassword);
System.out.println(“字符密碼:”+charPassword);
輸出
字符串密碼:Unknown
字符密碼:[C@110b053
如何使用雙重檢查鎖定在Java中創(chuàng)建線程安全的單例?
這個(gè)Java問(wèn)題也常被問(wèn):什么是線程安全的單例,你怎么創(chuàng)建它。好吧,在Java5之前的版本,使用雙重檢查鎖定創(chuàng)建單例Singleton時(shí),如果多個(gè)線程試圖同時(shí)創(chuàng)建Singleton實(shí)例,則可能有多個(gè)Singleton實(shí)例被創(chuàng)建。從Java5開(kāi)始,使用Enum創(chuàng)建線程安全的Singleton很容易。但如果面試官堅(jiān)持雙重檢查鎖定,那么你必須為他們編寫(xiě)代碼。記得使用volatile變量。
為什么枚舉單例在Java中更好
枚舉單例是使用一個(gè)實(shí)例在Java中實(shí)現(xiàn)單例模式的新方法。雖然Java中的單例模式存在很長(zhǎng)時(shí)間,但枚舉單例是相對(duì)較新的概念,在引入Enum作為關(guān)鍵字和功能之后,從Java5開(kāi)始在實(shí)踐中。本文與之前關(guān)于Singleton的內(nèi)容有些相關(guān),其中討論了有關(guān)Singleton模式的面試中的常見(jiàn)問(wèn)題,以及10個(gè)Java枚舉示例,其中我們看到了如何通用枚舉可以。這篇文章是關(guān)于為什么我們應(yīng)該使用Eeame作為Java中的單例,它比傳統(tǒng)的單例方法相比有什么好處等等。
Java枚舉和單例模式
Java中的枚舉單例模式是使用枚舉在Java中實(shí)現(xiàn)單例模式。單例模式在Java中早有應(yīng)用,但使用枚舉類(lèi)型創(chuàng)建單例模式時(shí)間卻不長(zhǎng).如果感興趣,你可以了解下構(gòu)建者設(shè)計(jì)模式和裝飾器設(shè)計(jì)模式。
1)枚舉單例易于書(shū)寫(xiě)
這是迄今為止最大的優(yōu)勢(shì),如果你在Java5之前一直在編寫(xiě)單例,你知道,即使雙檢查鎖定,你仍可以有多個(gè)實(shí)例。雖然這個(gè)問(wèn)題通過(guò)Java內(nèi)存模型的改進(jìn)已經(jīng)解決了,從Java5開(kāi)始的volatile類(lèi)型變量提供了保證,但是對(duì)于許多初學(xué)者來(lái)說(shuō),編寫(xiě)起來(lái)仍然很棘手。與同步雙檢查鎖定相比,枚舉單例實(shí)在是太簡(jiǎn)單了。如果你不相信,那就比較一下下面的傳統(tǒng)雙檢查鎖定單例和枚舉單例的代碼:
在Java中使用枚舉的單例
這是我們通常聲明枚舉的單例的方式,它可能包含實(shí)例變量和實(shí)例方法,但為了簡(jiǎn)單起見(jiàn),我沒(méi)有使用任何實(shí)例方法,只是要注意,如果你使用的實(shí)例方法且該方法能改變對(duì)象的狀態(tài)的話,則需要確保該方法的線程安全。默認(rèn)情況下,創(chuàng)建枚舉實(shí)例是線程安全的,但Enum上的任何其他方法是否線程安全都是程序員的責(zé)任。
你可以通過(guò)EasySingleton.INSTANCE來(lái)處理它,這比在單例上調(diào)用getInstance()方法容易得多。
具有雙檢查鎖定的單例示例
下面的代碼是單例模式中雙重檢查鎖定的示例,此處的getInstance()方法檢查兩次,以查看INSTANCE是否為空,這就是為什么它被稱(chēng)為雙檢查鎖定模式,請(qǐng)記住,雙檢查鎖定是代理之前Java5,但Java5內(nèi)存模型中易失變量的干擾,它應(yīng)該工作完美。
你可以調(diào)用DoubleCheckedLockingSingleton.getInstance()來(lái)獲取此單例類(lèi)的訪問(wèn)權(quán)限。
現(xiàn)在,只需查看創(chuàng)建延遲加載的線程安全的Singleton所需的代碼量。使用枚舉單例模式,你可以在一行中具有該模式,因?yàn)閯?chuàng)建枚舉實(shí)例是線程安全的,并且由JVM進(jìn)行。
人們可能會(huì)爭(zhēng)辯說(shuō),有更好的方法來(lái)編寫(xiě)Singleton而不是雙檢查鎖定方法,但每種方法都有自己的優(yōu)點(diǎn)和缺點(diǎn),就像我最喜歡在類(lèi)加載時(shí)創(chuàng)建的靜態(tài)字段Singleton,如下面所示,但請(qǐng)記住,這不是一個(gè)延遲加載單例:
單例模式用靜態(tài)工廠方法
這是我最喜歡的在Java中影響Singleton模式的方法之一,因?yàn)镾ingleton實(shí)例是靜態(tài)的,并且最后一個(gè)變量在類(lèi)首次加載到內(nèi)存時(shí)初始化,因此實(shí)例的創(chuàng)建本質(zhì)上是線程安全的。
你可以調(diào)用Singleton.getSingleton()來(lái)獲取此類(lèi)的訪問(wèn)權(quán)限。
2)枚舉單例自行處理序列化
傳統(tǒng)單例的另一個(gè)問(wèn)題是,一旦實(shí)現(xiàn)可序列化接口,它們就不再是Singleton,因?yàn)閞eadObject()方法總是返回一個(gè)新實(shí)例,就像Java中的構(gòu)造函數(shù)一樣。通過(guò)使用readResolve()方法,通過(guò)在以下示例中替換Singeton來(lái)避免這種情況:
如果Singleton類(lèi)保持內(nèi)部狀態(tài),這將變得更加復(fù)雜,因?yàn)槟阈枰獦?biāo)記為transient(不被序列化),但使用枚舉單例,序列化由JVM進(jìn)行。
3)創(chuàng)建枚舉實(shí)例是線程安全的
如第1點(diǎn)所述,因?yàn)镋num實(shí)例的創(chuàng)建在默認(rèn)情況下是線程安全的,你無(wú)需擔(dān)心是否要做雙重檢查鎖定。
總之,在保證序列化和線程安全的情況下,使用兩行代碼枚舉單例模式是在Java5以后的世界中創(chuàng)建Singleton的最佳方式。你仍然可以使用其他流行的方法,如你覺(jué)得更好,歡迎討論。
以上就是長(zhǎng)沙達(dá)內(nèi)教育java培訓(xùn)機(jī)構(gòu)的小編針對(duì)“兩道Java中常見(jiàn)面試題,快來(lái)挑戰(zhàn)下吧”的內(nèi)容進(jìn)行的回答,希望對(duì)大家有所幫助,如有疑問(wèn),請(qǐng)?jiān)诰€咨詢,有專(zhuān)業(yè)老師隨時(shí)為你服務(wù)。
Java面試題