瞎嘮嘮
寫一篇文章容易嗎?太不容易了,首先,需要一個(gè)安靜的環(huán)境,這一點(diǎn)就非常不容易。很多小伙伴的辦公室都是開(kāi)放式的,非常吵,況且上班時(shí)間寫的話,領(lǐng)導(dǎo)就不高興了;只能抽時(shí)間寫。其次,環(huán)境有了,還要有一顆安靜的心,如果心里裝著其他揮之不去的事,那就糟糕了,呆坐著電腦前一整天也不會(huì)有結(jié)果。
我十分佩服一些同行,他們寫萬(wàn)字長(zhǎng)文,這在我看來(lái),幾乎不太可能完成。因?yàn)槲乙崭?,一萬(wàn)字的長(zhǎng)文,如果走原創(chuàng)的話,至少需要一周時(shí)間,甚至一個(gè)月的時(shí)間。
就如小伙伴們看到的,我寫的文章大致都能在五分鐘內(nèi)閱讀完,并且能夠保證小伙伴們?cè)陂喿x完學(xué)到或者溫習(xí)到一些知識(shí)。這就是我的風(fēng)格,通俗易懂,輕松幽默。
好了,又一篇系列的文章它來(lái)了:你竟然還不會(huì)用 final 關(guān)鍵字。
已經(jīng)晚上 9 點(diǎn)半了,我還沒(méi)有下班,因?yàn)橐托聛?lái)的小伙伴一塊修復(fù)一個(gè) bug。我訂了一份至尊披薩,和小伙伴吃得津津有味的時(shí)候,他突然問(wèn)了我一個(gè)問(wèn)題:“老大,能給我詳細(xì)地說(shuō)說(shuō) final 關(guān)鍵字嗎,總感覺(jué)對(duì)這個(gè)關(guān)鍵字的認(rèn)知不夠全面?!?/p>
一下子我的火氣就來(lái)了,盡管小王問(wèn)的態(tài)度很謙遜,很卑微,但我還是忍不住破口大罵:“xx,你竟然不會(huì)用 final,我當(dāng)初是怎么面試你進(jìn)來(lái)的!”
發(fā)火歸發(fā)火,我這個(gè)人還是有原則的,等十點(diǎn)半回到家后,我決定為小伙伴專門寫一篇文章,好好地講一講 final 關(guān)鍵字,也希望給更多的小伙伴一些幫助。
盡管繼承可以讓我們重用現(xiàn)有代碼,但有時(shí)處于某些原因,我們確實(shí)需要對(duì)可擴(kuò)展性進(jìn)行限制,final 關(guān)鍵字可以幫助我們做到這一點(diǎn)。
01、final 類
如果一個(gè)類使用了 final 關(guān)鍵字修飾,那么它就無(wú)法被繼承。如果小伙伴們細(xì)心觀察的話,Java 就有不少 final 類,比如說(shuō)最常見(jiàn)的 String 類。
publicfinalclassString
implementsjava.io.Serializable,Comparable,CharSequence,
Constable,ConstantDesc?{}
為什么 String 類要設(shè)計(jì)成 final 的呢?原因大致有以下三個(gè):
為了實(shí)現(xiàn)字符串常量池
為了線程安全
為了 HashCode 的不可變性
更詳細(xì)的原因,可以查看我之前寫的一篇文章。
任何嘗試從 final 類繼承的行為將會(huì)引發(fā)編譯錯(cuò)誤,為了驗(yàn)證這一點(diǎn),我們來(lái)看下面這個(gè)例子,Writer 類似 final 的。
publicfinalclassWriter{
privateString?name;
publicStringgetName(){
returnname;
}
publicvoidsetName(String?name){
this.name?=?name;
}
}
嘗試去繼承它,編譯器會(huì)提示以下錯(cuò)誤,Writer 類是 final 的,無(wú)法繼承。
不過(guò),類似 final 的,并不意味著該類的對(duì)象是不可變的。
Writer?writer?=newWriter();
writer.setName("小伙伴");
System.out.println(writer.getName());//?小伙伴
Writer 的 name 字段的默認(rèn)值是 null,但可以通過(guò) settter 方法將其更改為“小伙伴”。也就是說(shuō),如果一個(gè)類只是 final 的,那么它并不是不可變的全部條件。
如果,你想了解不可變類的全部真相,請(qǐng)查看我之前寫的文章這次要說(shuō)不明白immutable類,我就怎么地。突然發(fā)現(xiàn),寫系列文章真的妙啊,很多相關(guān)性的概念全部涉及到了。我真服了自己了。
把一個(gè)類設(shè)計(jì)成 final 的,有其安全方面的考慮,但不應(yīng)該故意為之,因?yàn)榘岩粋€(gè)類定義成 final 的,意味著它沒(méi)辦法繼承,假如這個(gè)類的一些方法存在一些問(wèn)題的話,我們就無(wú)法通過(guò)重寫的方式去修復(fù)它。
02、final 方法
被 final 修飾的方法不能被重寫。如果我們?cè)谠O(shè)計(jì)一個(gè)類的時(shí)候,認(rèn)為某些方法不應(yīng)該被重寫,就應(yīng)該把它設(shè)計(jì)成 final 的。
Thread 類就是一個(gè)例子,它本身不是 final 的,這意味著我們可以擴(kuò)展它,但它的 isAlive() 方法是 final 答:
publicclassThreadimplementsRunnable{
publicfinalnativebooleanisAlive();
}
需要注意的是,該方法是一個(gè)本地(native)方法,用于確認(rèn)線程是否處于活躍狀態(tài)。而本地方法是由操作系統(tǒng)決定的,因此重寫該方法并不容易實(shí)現(xiàn)。
Actor 類有一個(gè) final 方法 show():
publicclassActor{
publicfinalvoidshow(){
}
}
當(dāng)我們想要重寫該方法的話,就會(huì)出現(xiàn)編譯錯(cuò)誤:
如果一個(gè)類中的某些方法要被其他方法調(diào)用,則應(yīng)考慮事被調(diào)用的方法稱為 final 方法,否則,重寫該方法會(huì)影響到調(diào)用方法的使用。
一個(gè)類是 final 的,和一個(gè)類不是 final,但它所有的方法都是 final 的,考慮一下,它們之間有什么區(qū)別?
我能想到的一點(diǎn),就是前者不能被繼承,也就是說(shuō)方法無(wú)法被重寫;后者呢,可以被繼承,然后追加一些非 final 的方法。沒(méi)毛病吧?看把我聰明的。
03、final 變量
被 final 修飾的變量無(wú)法重新賦值。換句話說(shuō),final 變量一旦初始化,就無(wú)法更改。之前被一個(gè)小伙伴問(wèn)過(guò),什么是 effective final,什么是 final,這一點(diǎn),我在之前的文章也有闡述過(guò)。
1)final 修飾的基本數(shù)據(jù)類型
來(lái)聲明一個(gè) final 修飾的 int 類型的變量:
finalintage?=18;
嘗試將它修改為 30,結(jié)果編譯器生氣了:
2)final 修飾的引用類型
現(xiàn)在有一個(gè)普通的類 Pig,它有一個(gè)字段 name:
publicclassPig{
privateString?name;
publicStringgetName(){
returnname;
}
publicvoidsetName(String?name){
this.name?=?name;
}
}
在測(cè)試類中聲明一個(gè) final 修飾的 Pig 對(duì)象:
finalPig?pig?=newPig();
如果嘗試將 pig 重新賦值的話,編譯器同樣會(huì)生氣:
但我們?nèi)匀豢梢匀バ薷?Pig 的字段值:
finalPig?pig?=newPig();
pig.setName("特立獨(dú)行");
System.out.println(pig.getName());//?特立獨(dú)行
3)final 修飾的字段
final 修飾的字段可以分為兩種,一種是 static 的,另外一種是沒(méi)有 static 的,就像下面這樣:
publicclassPig{
privatefinalintage?=1;
publicstaticfinaldoublePRICE?=36.5;
}
非 static 的 final 字段必須有一個(gè)默認(rèn)值,否則編譯器將會(huì)提醒沒(méi)有初始化:
static 的 final 字段也叫常量,它的名字應(yīng)該為大寫,可以在聲明的時(shí)候初始化,也可以通過(guò) static [代碼塊初始化]()。
4) final 修飾的參數(shù)
final 關(guān)鍵字還可以修飾參數(shù),它意味著參數(shù)在方法體內(nèi)不能被再修改:
publicclassArgFinalTest{
publicvoidarg(finalintage){
}
publicvoidarg1(finalString?name){
}
}
如果嘗試去修改它的話,編譯器會(huì)提示以下錯(cuò)誤:
04、總結(jié)
親愛(ài)的讀者朋友,我應(yīng)該說(shuō)得很全面了吧?我想小伙伴看到了這篇文章后一定會(huì)感謝我的良苦用心的,他畢竟是個(gè)積極好學(xué)的好同事啊。編輯不易,希望看到的小伙伴多多轉(zhuǎn)發(fā),收藏,給小編一個(gè) 關(guān)注!感謝您的閱讀,下面小編給大家準(zhǔn)備了兩份java高并發(fā)學(xué)習(xí)資料。免費(fèi)送給大家!
一,java高并發(fā)實(shí)戰(zhàn)詳解+實(shí)戰(zhàn)java高并發(fā)程序設(shè)計(jì)
二,java大佬馬士兵老師內(nèi)部高并發(fā)編程視頻
想獲取這兩份學(xué)習(xí)資料的小伙伴,關(guān)注小編,轉(zhuǎn)發(fā),收藏文章,添加w?:bjmsb07 即可免費(fèi)獲得