文章目錄
1.什么是final關(guān)鍵字(概念)
2.final關(guān)鍵字基本用法
3.深入理解final關(guān)鍵字
4.final 關(guān)鍵字的最佳實踐
什么是final關(guān)鍵字(概念)
談到final關(guān)鍵字,想必很多人都不陌生,在使用匿名內(nèi)部類的時候可能會經(jīng)常用到final關(guān)鍵字 。final 是 Java 中的一個關(guān)鍵字,可以用于修飾類、方法和變量。當(dāng)一個類被聲明為 final 時,它意味著該類不能被繼承。當(dāng)一個方法被聲明為 final 時,它意味著該方法不能被重寫。當(dāng)一個變量被聲明為 final 時,它意味著該變量的值不能被修改。
?final關(guān)鍵字基本用法
常見有5種用法,我們來歸納總結(jié)一下:
1. 用來修飾一個類
2. 用來修飾一個方法
3. 用來修飾成員變量
4. 用來修飾局部變量
5. 用來修飾方法參數(shù)
final飾修類?
如果聲明一個類為final類,? 那么這個類就是最終類,不能被繼承
public final class ParentClass { public void happy() { System.out.println("高興"); } }
當(dāng)寫一個類去繼承它的時候
public class ChildClass extends ParentClass{ }
就會報錯錯誤;
注意:一個類如果是final的,那么其中所有的成員方法都無法進行覆蓋重寫。
final類中的成員變量可以根據(jù)需要設(shè)為final,但是final類中的所有成員方法都會被隱式地指定為final方法。 在使用final修飾類的時候,一定要謹慎選擇,除非這個類以后不會用來繼承或者出于安全考慮,盡量不要將類設(shè)計為final類。
final修飾方法?
當(dāng)final用來修飾一個方法的時候,這個方法就是最終方法,那么很明顯就是說不能被覆蓋重寫。
public class ParentClass { public void happy() { System.out.println("高興"); } //用final關(guān)鍵字修飾的方法 protected final void play(){ System.out.println("開心的玩耍"); } }
我們在繼承類中去看下 play()方法是不可以被override的,也就是是報錯,說明 final修飾的方法,是一個最終方法,不能被子類去覆蓋重寫。
“使用final方法的原因有兩個。第一個原因是把方法鎖定,以防任何繼承類修改它的含義;第二個原因是效率。在早期的Java實現(xiàn)版本中,會將final方法轉(zhuǎn)為內(nèi)嵌調(diào)用。但是如果方法過于龐大,可能看不到內(nèi)嵌調(diào)用帶來的任何性能提升。在最近的Java版本中,不需要使用final方法進行這些優(yōu)化了?!?br> 因此,如果只有在想明確禁止 該方法在子類中被覆蓋的情況下才將方法設(shè)置為final的。即父類的final方法是不能被子類所覆蓋的,也就是說子類是不能夠存在和父類一模一樣的方法的。
final修飾的方法表示此方法已經(jīng)是“最后的、最終的”含義,亦即此方法不能被重寫(可以重載多個final修飾的方法)。此處需要注意的一點是:因為重寫的前提是子類可以從父類中繼承此方法,如果父類中final修飾的方法同時訪問控制權(quán)限為private,將會導(dǎo)致子類中不能直接繼承到此方法,因此,此時可以在子類中定義相同的方法名和參數(shù),此時不再產(chǎn)生重寫與final的矛盾,而是在子類中重新定義了新的方法。(注:類的private方法會隱式地被指定為final方法)
final修飾變量
final成員變量表示常量,只能被賦值一次,賦值后值不再改變。
當(dāng)final修飾一個基本數(shù)據(jù)類型時,表示該基本數(shù)據(jù)類型的值一旦在初始化后便不能發(fā)生變化;如果final修飾一個引用類型時,則在對其初始化之后便不能再讓其指向其他對象了,但該引用所指向的對象的內(nèi)容是可以發(fā)生變化的。本質(zhì)上是一回事,因為引用的值是一個地址,final要求值,即地址的值不發(fā)生變化。
final修飾一個成員變量(屬性),必須要顯示初始化。這里有兩種初始化方式,一種是在變量聲明的時候初始化;第二種方法是在聲明變量的時候不賦初值,但是要在這個變量所在的類的所有的構(gòu)造函數(shù)中對這個變量賦初值。class Animal { private final int count = 0; public Animal() { count = 1; //報錯 final Object object = new Object(); object = new Object(); //報錯 } }
深入理解final關(guān)鍵字?
類的final變量和普通變量的區(qū)別
當(dāng)用final作用于類的成員變量時,成員變量(注意是類的成員變量,局部變量只需要保證在使用之前被初始化賦值即可)必須在定義時或者構(gòu)造器中進行初始化賦值,而且final變量一旦被初始化賦值之后,就不能再被賦值了。
那么final變量和普通變量到底有何區(qū)別呢?下面請看一個例子:public class Test { public static void main(String[] args) { String a = "helloworld"; final String b = "hello"; String c = "hello"; String x = b + "world"; String y = c + "world"; System.out.println(a == x); System.out.println(a == y); } }
輸出結(jié)果:true ; false
大家可以先想一下這道題的輸出結(jié)果。為什么第一個比較結(jié)果為true,而第二個比較結(jié)果為fasle。這里面就是final變量和普通變量的區(qū)別了,當(dāng)final變量是基本數(shù)據(jù)類型以及String類型時,如果在編譯期間能知道它的確切值,則編譯器會把它當(dāng)做編譯期常量使用。也就是說在用到該final變量的地方,相當(dāng)于直接訪問的這個常量,不需要在運行時確定。這種和C語言中的宏替換有點像。因此在上面的一段代碼中,由于變量b被final修飾,因此會被當(dāng)做編譯器常量,所以在使用到b的地方會直接將變量b 替換為它的值。而對于變量d的訪問卻需要在運行時通過鏈接來進行。想必其中的區(qū)別大家應(yīng)該明白了,不過要注意,只有在編譯期間能確切知道final變量值的情況下,編譯器才會進行這樣的優(yōu)化,比如下面的這段代碼就不會進行優(yōu)化:
public class Test { public static void main(String[] args) { String a = "helloworld"; final String b = getHello(); String x = b + "world"; System.out.println(a == x); } public static String getHello() { return "hello"; } }
這段代碼的輸出結(jié)果為false。這里要注意一點就是:不要以為某些數(shù)據(jù)是final就可以在編譯期知道其值,通過變量b我們就知道了,在這里是使用getHello()方法對其進行初始化,他要在運行期才能知道其值。
被final修飾的引用變量指向的對象內(nèi)容可變?
在上面提到被final修飾的引用變量一旦初始化賦值之后就不能再指向其他的對象,那么該引用變量指向的對象的內(nèi)容可變嗎?看下面這個例子:
public class Test { public static void main(String[] args) { final Object object = new Object(); System.out.println(++object.i); } } class Object { public int i = 0; }
輸出結(jié)果: 1
這段代碼可以順利編譯通過并且有輸出結(jié)果,輸出結(jié)果為1。這說明引用變量被final修飾之后,雖然不能再指向其他對象,但是它指向的對象的內(nèi)容是可變的。
?final參數(shù)的問題
在實際應(yīng)用中,我們除了可以用final修飾成員變量、成員方法、類,還可以修飾參數(shù)、若某個參數(shù)被final修飾了,則代表了該參數(shù)是不可改變的。如果在方法中我們修改了該參數(shù),則編譯器會提示你:The final local variable i cannot be assigned. It must be blank and not using a compound assignment??聪旅娴睦樱?mark hidden color="red">文章來源:http://www.zghlxwxcb.cn/news/detail-769482.html
public class TestFinal { public static void main(String[] args) { TestFinal testFinal = new TestFinal(); int i = 0; testFinal.changeValue(i); System.out.println(i); } public void changeValue(final int i) { //final參數(shù)不可改變 i++; //報錯,因為參數(shù)i已經(jīng)被final修飾了 System.out.println(i); } }
上面這段代碼changeValue方法中的參數(shù)i用final修飾之后,就不能在方法中更改變量i的值了。值得注意的一點,方法changeValue和main方法中的變量i根本就不是一個變量,因為java參數(shù)傳遞采用的是值傳遞,對于基本類型的變量,相當(dāng)于直接將變量進行了拷貝。所以即使沒有final修飾的情況下,在方法內(nèi)部改變了變量i的值也不會影響方法外的i。文章來源地址http://www.zghlxwxcb.cn/news/detail-769482.html
到了這里,關(guān)于淺析Java中的final關(guān)鍵字(詳細)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!