国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

String被設(shè)計(jì)成不可變和不能被繼承的原因

2019-11-08 03:04:06
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

String是所有語(yǔ)言中最常用的一個(gè)類。我們知道在java中,String是不可變的、final的。Java在運(yùn)行時(shí)也保存了一個(gè)字符串池(String pool),這使得String成為了一個(gè)特別的類。

主要是為了 “ 效率 ” 和 “ 安全性 ” 的緣故。 若 String 允許被繼承, 由于它的高度被使用率, 可能會(huì)降低程序的性能,所以 String 被定義成 final。

 

一:String 和其他基本類型不同 , 他是個(gè)對(duì)象類型. 既然是對(duì)象類型 , 如果是在靜態(tài)方法下是必須調(diào)用靜態(tài)方法或值的 , 如果是非靜態(tài)的方法 , 就必須要實(shí)例化.

 

main 函數(shù)是個(gè) static 的. 所以String 要能像其他的基本類型一樣直接被調(diào)用. 這也是為什么在 main 函數(shù)下使用 String 類型不會(huì)報(bào)告錯(cuò)誤的原因..

 

一下就解釋了兩個(gè)心里的疑問..

 

以前一直覺得奇怪 ,為什么 String 是對(duì)象類型在 main 函數(shù)下卻是不需要實(shí)例化的. 再次佩服 java 設(shè)計(jì)人員想得真周到.

 

二:當(dāng)定義 String 類型的靜態(tài)字段(也成類字段),可以用靜態(tài)變量(非 final)代替常量(final)加快程序速度。 反之,對(duì)于原始數(shù)據(jù)類型,例如 int,也成立。

 

例如,你可能創(chuàng)建一個(gè)如下的 String 對(duì)象:

 

PRivatestaticfinal Stringx="example";

對(duì)于這個(gè)靜態(tài)常量(由 final 關(guān)鍵字標(biāo)識(shí)),你使用常量的每個(gè)時(shí)候都會(huì)創(chuàng)建一個(gè)臨時(shí)的 String 對(duì)象。 在字節(jié)代碼中,編譯器去掉 ”x”,代替它的是字符串 “example”, 以致每次引用 ”x” 時(shí) VM 都會(huì)進(jìn)行一次哈希表查詢。

 

相比之下,度于靜態(tài)變量 ( 非 final 關(guān)鍵字 ),字符串只創(chuàng)建一次。 僅當(dāng)初始化 “x” 時(shí), VM 才進(jìn)行哈希表查詢。

 

還有另一個(gè)解釋 :

帶有 final 修飾符的類是不可派生的。 在 java 核心 API 中,有許多應(yīng)用 final 的例子,例如 java.lang.String。 為 String 類指定 final 防止了人們覆蓋 length() 方法。

 

另外,如果指定一個(gè)類為 final,則該類所有的方法都是 final。 java 編譯器會(huì)尋找機(jī)會(huì)內(nèi)聯(lián)(inline)所有的 final 方法(這和具體的編譯器實(shí)現(xiàn)有關(guān))。 此舉能夠使性能平均提高 50%。

 

示例:

 

publicclassTest{

publicstaticvoidmain(String[]args){

//

}

}

如果 String 不是 final 那么就可以繼承

 

publicclassString2extendsString{

//..

//...

}

那我們的 main 也就可以寫成

 

publicclassTest{

publicstaticvoidmain(String2[]args){//注意此處

//

}

}

英文參考:http://forums.sun.com/thread.jspa?threadID=636414

 

另外補(bǔ)充一點(diǎn):

作用就是 final的類不能被繼承,不能讓別人繼承有什么好處?

 

意義就在于,安全性,如此這般:

java 自出生那天起就是“為人民服務(wù)”,這也就是為什么java做不了病毒,也不一定非得是病毒,反正總之就是為了安全, 人家java的開發(fā)者目的就是不想讓 java干這類危險(xiǎn)的事兒,java并不是操作系統(tǒng)本地語(yǔ)言, 換句話說(shuō)java必須借助操作系統(tǒng)本身的力量才能做事,JDK中提供的好多核心類比如 String,這類的類的內(nèi)部好多方法的實(shí)現(xiàn)都不是java編程語(yǔ)言本身編寫的, 好多方法都是調(diào)用的操作系統(tǒng)本地的API,這就是著名的“本地方法調(diào)用”,也只有這樣才能做事,這種類是非常底層的, 和操作系統(tǒng)交流頻繁的,那么如果這種類可以被繼承的話,如果我們?cè)侔阉姆椒ㄖ貙懥耍僮飨到y(tǒng)內(nèi)部寫入一段具有惡意攻擊性質(zhì)的代碼什么的, 這不就成了核心病毒了么?

 

上面所述是最重要的,另外一個(gè)方面,上面2位老兄說(shuō)的也都很對(duì), 就是不希望別人改,這個(gè)類就像一個(gè)工具一樣,類的提供者給我們提供了, 就希望我們直接用就完了,不想讓我們隨便能改,其實(shí)說(shuō)白了還是安全性, 如果隨便能改了,那么java編寫的程序肯定就很不穩(wěn)定,你可以保證自己不亂改, 但是將來(lái)一個(gè)項(xiàng)目好多人來(lái)做,管不了別人,再說(shuō)有時(shí)候萬(wàn)一疏忽了呢?他也不是估計(jì)的, 所以這個(gè)安全性是很重要的,java和C++相比,優(yōu)點(diǎn)之一就包括這一點(diǎn);

 

原因絕對(duì)不只有這么多,因?yàn)槿绻@些個(gè)核心的類都能被隨便操作的話,那是很恐怖的,會(huì)出現(xiàn)好多好多未知的錯(cuò)誤,莫名其妙的錯(cuò)誤….

 

String類不可變性的好處:

 

只有當(dāng)字符串是不可變的,字符串池才有可能實(shí)現(xiàn)。字符串池的實(shí)現(xiàn)可以在運(yùn)行時(shí)節(jié)約很多heap空間,因?yàn)椴煌淖址兞慷贾赶虺刂械耐粋€(gè)字符串。但如果字符串是可變的,那么String interning將不能實(shí)現(xiàn)(譯者注:String interning是指對(duì)不同的字符串僅僅只保存一個(gè),即不會(huì)保存多個(gè)相同的字符串。),因?yàn)檫@樣的話,如果變量改變了它的值,那么其它指向這個(gè)值的變量的值也會(huì)一起改變。

 

如果字符串是可變的,那么會(huì)引起很嚴(yán)重的安全問題。譬如,數(shù)據(jù)庫(kù)的用戶名、密碼都是以字符串的形式傳入來(lái)獲得數(shù)據(jù)庫(kù)的連接,或者在socket編程中,主機(jī)名和端口都是以字符串的形式傳入。因?yàn)樽址遣豢勺兊模运?#20540;是不可改變的,否則黑客們可以鉆到空子,改變字符串指向的對(duì)象的值,造成安全漏洞。

 

因?yàn)樽址遣豢勺兊模允嵌嗑€程安全的,同一個(gè)字符串實(shí)例可以被多個(gè)線程共享。這樣便不用因?yàn)榫€程安全問題而使用同步。字符串自己便是線程安全的。

 

類加載器要用到字符串,不可變性提供了安全性,以便正確的類被加載。譬如你想加載java.sql.Connection類,而這個(gè)值被改成了myhacked.Connection,那么會(huì)對(duì)你的數(shù)據(jù)庫(kù)造成不可知的破壞。

 

因?yàn)樽址遣豢勺兊模栽谒鼊?chuàng)建的時(shí)候hashcode就被緩存了,不需要重新計(jì)算。這就使得字符串很適合作為Map中的鍵,字符串的處理速度要快過其它的鍵對(duì)象。這就是HashMap中的鍵往往都使用字符串 


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 泾阳县| 西充县| 井研县| 高密市| 大港区| 酒泉市| 七台河市| 靖西县| 鄂尔多斯市| 黄平县| 黄冈市| 正镶白旗| 镇康县| 商南县| 安平县| 瑞金市| 上栗县| 陆丰市| 弥勒县| 城口县| 双流县| 兰考县| 舞阳县| 乐陵市| 鞍山市| 综艺| 泸州市| 桦川县| 宣武区| 都昌县| 剑阁县| 竹北市| 清水河县| 九龙县| 黄骅市| 磴口县| 准格尔旗| 安化县| 嘉兴市| 成武县| 贵溪市|