自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

對話式情景剖析,String被Final修飾的真正原因!一篇足矣

開發(fā) 前端
當面試官問道為什么 String 是final的時候,要答出兩方面:第一就是final char value[] 的final ;第二就是 final class 的final。

[[270572]]

面試官:你好,能看得清下面這張圖嗎?

 

對話式情景剖析,String被final修飾的真正原因!一篇足矣

我:可以的。

面試官:恩,好的。呃,你能不能說一說為什么String要用final修飾?

我:final意味著不能被繼承或者被重寫,String類用final修飾是Java的設計人員不希望客戶端程序員繼承String類,并有可能改寫String類中的方法。使用String對象的***實踐,應該是關聯(lián)或者依賴,而不是繼承。

面試官:恩,你還沒有說到點兒上,能再展開談談嗎?

我:恩,好的。具體來說,String類被定義為final的主要是從兩個方面來考慮:安全和性能,也就是說,String被設計成final的,即考慮到了安全性,也兼顧了性能問題。

我們可以看到上面這張圖中,出現(xiàn)了兩個final。一個final是修飾了String類,而另一個final修飾了char數(shù)組。我們知道,String的本質實際上就是這個char數(shù)組,先來說一說 final char[] 的這個 final。

用final修飾char數(shù)組的原因,還需要從我們日常的實際開發(fā)中說起。

在日常的實際開發(fā)中,開發(fā)者會用到大量的字符串對象,可以說我們無時無刻不在和字符串打交道。大量的字符串被輕易的創(chuàng)建出來,這就涉及到一個非常嚴重的問題,即性能的開銷,我們知道分配給Java虛擬機的內存是有限的,如果不加節(jié)制的創(chuàng)建字符串對象,那么弊端顯而易見:內存迅速被占滿,程序執(zhí)行緩慢!!!于是Java的設計者采用了一種非常有效的解決辦法,即:共享字符串。共享字符串對象的方法是將字符串對象存放到虛擬機中的方法區(qū)里面的常量池里,不同的類,不同的方法,甚至是不同的線程,可以使用同一個字符串對象,而不需要再在內存中開辟新的內存空間,從而極大的降低了內存的消耗,也提升了程序運行效率。

因此,字符串共享是解決內存消耗以及龐大的性能開銷的必然選擇。但是到這里為止,還不能解釋為什么這個char數(shù)組要用final修飾。用final修飾的原因來自于另一個必須要考慮的問題:安全性。什么是安全性?這里的安全性,指的是線程安全性,這個很好理解,首先,我們已經(jīng)確定了一個大的前提:字符串要共享,否則內存將瞬間擠爆、性能將嚴重下降。

但是共享的問題在于:不同的線程有可能會修改這個共享對象。

比如,thread_1正在循環(huán)一個List,每個元素和 “abc” 進行比較,同時thread_2也在使用這個 “abc” 對象,如果thread_2改變了這個共享字符串,結果會怎樣?很明顯,thread_1 的結果將不可預測!!因此,解決共享變量安全性的***的手段,就是禁止修改共享對象,于是字符串對象的這個char數(shù)組就必然要被 final 修飾了,因為 final 意味著禁止改變。

面試官:恩恩,沒想到你的想法這么透徹!那么,這是char數(shù)組final的作用,那為什么還要給String類本身加一個final呢?

我:恩,這也是另一個Java設計者需要考慮的問題。既然共享字符數(shù)組已經(jīng)確定是final的、不能改變的了,那為什么要給String也加一個final呢?原因依然是性能和安全性兩個方面。

但是,此時需要考慮的性能和安全性卻和 final char[] 的final 不太一樣了。

首先,如果假設String可以被繼承,那么方法也可以被重寫,這里面涉及到一個C++中的概念,叫做:虛函數(shù)表。

面試官:哦?你還懂C++?

 

 

 

[[270573]]

 

 

 

我: 是的。同樣是面向對象的語言,Java和C++有著共通的地方。首先,虛函數(shù)是指:可以定義一個父類的指針, 其指向一個子類對象, 當通過父類的指針去調用函數(shù)時, 可以在運行時決定應該調用父類的函數(shù)還是子類的函數(shù)。虛函數(shù)是實現(xiàn)多態(tài)的基礎。前面說了,如果String可以被繼承,那么勢必就會有人通過創(chuàng)建String引用并指向String子類對象的方式,來使用子類的方法,比如像這樣寫:

  1. String aa = new SubString("abcd"); 
  2. aa.length(); 

這看似沒有什么問題,但是問題在于性能,前面提到了,在程序開發(fā)過程中,字符串對象是非常常用的,上述代碼在調用對象aa.length() 時,虛擬機就會去虛函數(shù)表中查找并判定究竟是應該調用哪個子類的length()方法。在大量使用字符串對象的場景下,勢必會降低程序運行效率。

其次又是安全性,這個安全性的解釋為語義的安全性,面向對象的語言本身就要求要有清晰的語義和明確的表達。String的各個方法都圍繞著一個char數(shù)組進行,所有方法的語義都是最直接、最有效的。重寫String的方法意味著:不一樣的語義或者錯誤的語義。這將直接導致String行為的不確定性,使用String對象的代碼將會是不安全的代碼。因此,Java設計者才會禁止任何人繼承String類,主要是為了String對象的操作語義不被改變,確保使用String對象的代碼是絕對安全的。

面試官:原來如此,沒想到你的理解這么到位!年薪50萬,明天就來上班吧!

 

[[270574]]

總結

當面試官問道為什么 String 是final的時候,要答出兩方面:***就是final char value[] 的final ;第二就是 final class 的final。

這兩個final都要緊扣安全與性能兩個方面闡述。

1、final char value[] 的final 要抓住幾個關鍵點是:value[]數(shù)組的final用于限制字符數(shù)組的修改。字符串將會被大量使用,從性能上考慮迫使Java語言的設計者將 char[] 設計為共享的,又因為字符串是共享的再次迫使設計者考慮到線程安全性,這才需要用final來修飾,避免并發(fā)場景下的行為不可預測。

2、final class 的final 要抓住幾個關鍵點是:類上的final用于限制產(chǎn)生子類(或限制多態(tài)/或限制行為的變化)。字符串的使用是頻繁的,如果通過多態(tài)的方式使用String子類對象及其方法將會一定程度上導致性能下降(多態(tài)的實現(xiàn)原理:底層的虛函數(shù)表),同時String中的方法也可能面臨被Override重寫的危險導致程序語義不安全、甚至是邏輯錯誤,與Java自始至終強調的安全性理念相違背。

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2022-08-26 10:32:21

MongoDB數(shù)據(jù)庫

2024-11-04 08:54:30

2021-01-14 07:15:19

NginxWeb服務器

2018-12-19 09:38:20

2023-10-10 08:24:12

2021-05-08 08:36:40

ObjectString前端

2024-04-08 10:01:33

2021-10-15 07:57:04

Docker 日志容器

2015-01-21 09:20:06

企業(yè)軟件更新

2018-04-18 16:16:40

2021-01-07 11:10:47

關鍵字

2019-05-07 11:57:26

分布式架構負載均衡

2021-05-28 10:02:05

Swift5 字符串String

2022-05-23 15:56:40

人工智能機器人自然語言

2022-07-06 12:07:06

Python函數(shù)式編程

2021-07-07 07:14:48

分布式ID分布式系統(tǒng)

2021-05-19 08:12:39

etcd分布式鎖分布式系統(tǒng)

2021-11-21 22:36:18

Java修飾符開發(fā)

2021-09-15 19:05:16

數(shù)據(jù)開源項目

2021-07-12 06:11:14

SkyWalking 儀表板UI篇
點贊
收藏

51CTO技術棧公眾號