夯實Java基礎(九)——final關鍵字

一、前言

Java語言中的final關鍵字,想必你們都不是很陌生,咱們本身用的最多的應該是用來定義常量吧,那麼今天咱們就來了解final這個關鍵字的用法,這個關鍵字仍是很是簡單的。html

final從字面意思是不可更改的,最終的意思,它能夠用來修飾類、方法、變量(包括成員變量和局部變量)、參數。優化

二、final修飾類

final修飾類,表示該類不能再被繼承了,若是一個類它的功能比較完整,不須要擴展功能,咱們就可使用final來修飾。咱們最經常使用String、Integer、System等類就是用final修飾的,其不能再被其餘類所繼承。this

用final修飾類若是被繼承了那麼在編譯的時候就會報錯。spa

三、修飾方法

final修飾方法,表示這個方法不能被子類方法重寫。若是你認爲一個方法的功能已經足夠完整了,不須要再去子類中擴展的話,咱們能夠聲明此方法爲final。好比Object類中getClass()方法就是final修飾的。code

 

注意:類中全部的private方法都自動成爲final。因爲不能訪問一個private方法,因此它絕對不會被覆蓋。htm

四、修飾變量

final修飾變量表示是常量,通常都和static一塊兒使用,用來定義全局常量。final不管修飾的是成員變量仍是局部變量,都必須進行顯式初始化,以下。對象

 1 public class FinalTest {
 2     //顯式初始化
 3     final int AA=11;
 4     final int BB;
 5     final int CC;
 6     final int DD;
 7     //構造代碼塊初始化
 8     {
 9         BB=22;
10     }
11     //構造方法初始化
12     public FinalTest(){
13         CC=33;
14         DD=44;
15     }
16 
17     public FinalTest(int CC, int DD) {
18         this.CC = CC;
19         this.DD = DD;
20     }
21 }

咱們能夠經過顯式初始化、構造代碼塊初始化、構造方法初始化這三種方式對final修飾的變量進行初始化。blog

前面都是講的final修飾基本數據類型的變量,若是final修飾引用變量會是怎麼樣,咱們來看一下舉例:繼承

 1 public class FinalTest {
 2 
 3     public static void main(String[] args) {
 4         final AA aa = new AA();
 5         //這裏在引用其餘的對象就會報錯Cannot assign a value to final variable 'aa'
 6         //aa=new AA();
 7         aa.i++;
 8         System.out.println(aa.i);
 9     }
10 
11 }
12 
13 class AA{
14     int i;
15 }
16 
17 //運行結果:1

能夠看到,雖然咱們將引用變量用final修飾了,可是該對象的變量 i 咱們仍是能夠進行修改,而這個變量的引用不能再指向另外一個對象了。代表final修飾的是引用變量,就不能再指向其餘對象,可是若是該對象內的變量不是final修飾的,其變量的值是能夠進行修改的。get

五、修飾參數

final修飾參數準確的來講應該是修飾形參,代表該形參的值不能被修改。

 1 public class FinalTest {
 2 
 3     public static void main(String[] args) {
 4         FinalTest f=new FinalTest();
 5         f.show(5);
 6     }
 7 
 8     public void show(final int param){
 9         //編譯報錯:Cannot assign a value to final variable 'param'
10         //param=10;
11         System.out.println(param);
12     }
13 }

我在使用final修飾形參時,代表此形參是一個常量。當咱們調用方法的時候,給形參進行賦值,一旦賦值之後,就只能在該方法使用,並且不能進行從新賦值操做,不然編譯報錯。若是形參是引用類型,則引用變量不能再指向其餘對象,可是該對象的內容是能夠改變的。

六、類的final變量和普通變量有什麼區別?

參考連接:http://www.javashuo.com/article/p-heipsycl-n.html

當用final做用於類的成員變量時,成員變量(注意是類的成員變量,局部變量只須要保證在使用以前被初始化賦值便可)必須在定義時或者構造器中進行初始化賦值,並且final變量一旦被初始化賦值以後,就不能再被賦值了。那麼final變量和普通變量到底有何區別呢?下面請看一個例子:

 1 public class Test { 
 2     public static void main(String[] args)  { 
 3         String a = "hello2";   
 4         final String b = "hello"; 
 5         String d = "hello"; 
 6         String c = b + 2;   
 7         String e = d + 2; 
 8         System.out.println((a == c)); 
 9         System.out.println((a == e)); 
10     } 
11 }

輸出結果:true、false
     你們能夠先想一下這道題的輸出結果。爲何第一個比較結果爲true,而第二個比較結果爲fasle。這裏面就是final變量和普通變量的區別了,當final變量是基本數據類型以及String類型時,若是在編譯期間能知道它的確切值,則編譯器會把它當作編譯期常量使用。也就是說在用到該final變量的地方,至關於直接訪問的這個常量,不須要在運行時肯定。這種和C語言中的宏替換有點像。所以在上面的一段代碼中,因爲變量b被final修飾,所以會被當作編譯器常量,因此在使用到b的地方會直接將變量b 替換爲它的值。而對於變量d的訪問卻須要在運行時經過連接來進行。想必其中的區別你們應該明白了,不過要注意,只有在編譯期間能確切知道final變量值的狀況下,編譯器纔會進行這樣的優化,好比下面的這段代碼就不會進行優化:

 1 public class Test { 
 2     public static void main(String[] args)  { 
 3         String a = "hello2";   
 4         final String b = getHello(); 
 5         String c = b + 2;   
 6         System.out.println((a == c)); 
 7   
 8     } 
 9       
10     public static String getHello() { 
11         return "hello"; 
12     } 
13 }

這段代碼的輸出結果爲false。這裏要注意一點就是:不要覺得某些數據是final就能夠在編譯期知道其值,經過變量b咱們就知道了,在這裏是使用getHello()方法對其進行初始化,他要在運行期才能知道其值。

相關文章
相關標籤/搜索