深入解析final关键字的用法
夫陶公清風(fēng)千古,余又何人,敢稱庶幾
個人博客地址:http://blog.breez.work
文章目錄
- 介紹
- 解析
- final屬性
- final方法
- final參數(shù)
- final類
介紹
final用于聲明屬性【屬性不可變】、方法【方法不可覆蓋】、類(除了抽象類)【類不可被繼承】
解析
final屬性
被final修飾的變量不可變。【引用不可變】
public class FinalTest {public static void main(String[] args) {final StringBuffer s = new StringBuffer("Hello");s.append(" World");System.out.println(s); //輸出Hello World} }public class FinalTest {public static void main(String[] args) {final StringBuffer s = new StringBuffer("Hello World");s = new StringBuffer("Hello world"); //編譯報錯} }
從上面可以看出final指的是引用不可變,即它只能指向初始化時指向的那個對象,不關(guān)心指向?qū)ο髢?nèi)容的變化。所以被final修飾的變量必須被初始化。
如何初始化:
- 在初始化塊中初始化:【編譯通過】
試圖在靜態(tài)初始化塊中初始化final變量【編譯報錯】
public class FinalTest {private final String name;// 編譯報錯static{name = "BreezAm"; //編譯報錯,就算name定義時已經(jīng)被初始化此處編譯期也會報錯}public static void main(String[] args) {FinalTest test = new FinalTest();String name = test.name;System.out.println(name);//BreezAm} }- 在靜態(tài)初始化塊中初始化成員變量【編譯通過】
- 試圖在靜態(tài)初始化塊中初始化成員變量【編譯報錯】
- 在構(gòu)造器中初始化非靜態(tài)final成員變量【編譯通過】
final方法
當(dāng)一個方法被聲明為final時,該方法不允許任何子類重寫這個方法,但子類仍然可以使用這個方法。[注意:final方法可以被重載]
另外,還有一種被稱為inline(內(nèi)聯(lián))的機制,當(dāng)調(diào)用一個被聲明為final的方法時,直接將方法主體插入到調(diào)用處,而不是進行方法調(diào)用(類似于C++中的inline),這樣做可以提高程序的效率。
案例:
/*** 父類*/ public class Father {/*** 編寫一個final方法*/public final void doAction(){System.out.println("我是final方法、我不可以被重寫,但是你可以用噢!渣女!!");} }子類試圖重寫final方法【編譯報錯】
/*** 子類*/ public class Children extends Father {public final void doAction(){ //編譯報錯、因為父類doAction方法是final類型的,所以不可以被重寫}public static void main(String[] args) {} }使用父類中的final方法【編譯通過】
/*** 子類*/ public class Children extends Father {public static void main(String[] args) {Children children = new Children();children.doAction();} }輸出:
我是final方法、我不可以被重寫,但是你可以用噢!渣女!!子類重載父類中的final方法
/*** 子類*/ public class Children extends Father {/*** 重寫父類中被聲明為final的方法* @param a* @param b*/public final void doAction(int a,int b){ // 可以被重載,哈哈,被我發(fā)現(xiàn)了System.out.println("a:"+a);System.out.println("b:"+b);}public static void main(String[] args) {Children children = new Children();children.doAction(20,30);} }輸出:
a:20 b:30final參數(shù)
用來表示這個參數(shù)在這個函數(shù)內(nèi)部不允許被修改
案例:
public class FinalTest {/*** 編寫一個帶參數(shù)為final的方法** @param name*//*public void doActionFinal(final String name) {name = "我想修改name,但是編譯報錯了,難過!!"; //編譯不通過}*//*** 編寫一個帶非final參數(shù)的方法** @param name*/public void doAction(String name) {System.out.println("修改前:" + name);name = "name參數(shù)不是final的,我修改成功了,一個字:巴適!"; //編譯通過System.out.println("修改后: " + name);}public static void main(String[] args) {FinalTest test = new FinalTest();//test.doActionFinal("BreezAm");test.doAction("BreezAm");} }輸出:
修改前:BreezAm 修改后: name參數(shù)不是final的,我修改成功了,一個字:巴適!final類
當(dāng)一個類被聲明為final時,此類不能被繼承,所有的方法都不能被重寫。但這并不表示final類的成員變量也是不可變的,要想做到final類的成員變量不可改變,必須給成員變量增加final修飾。注意:一個類不能即被聲明為abstract,又被聲明為final【抽象類不能聲明為final】。
試圖繼承被聲明為final的類【編譯失敗】
/*** 父類*/ public final class Father { } /*** 子類*/ public class Children extends Father { //編譯報錯}試圖將一個abstract類聲明為final【編譯失敗】
/*** 父類*/ public final abstract class Father { //編譯失敗,抽象類不能聲明為final}修改final類的成員變量
/*** 父類*/ public final class Father {private String name = "BreezAm";private final int num = 2018010110;public void doAction() {name = "清風(fēng)";//修改final類的非final成員變量 編譯通過num = 2019010110;//修改final類的final成員變量 編譯失敗} }創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎
總結(jié)
以上是生活随笔為你收集整理的深入解析final关键字的用法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。