final關鍵字用在三種情況下,數據、方法和類。
1.final數據,如果是基本數據類型,那么表明,這個基本數據必須在定義的時候初始化或者使用前進行初始化。如果是對象引用的話,那么表明它不能再指向其他的其他的對象,但是引用的對象本身是可以改變的。
FinalData.java
import java.util.*;

class Value{
?int i;
?public Value(int i){this.i=i;}
}

public class FinalData{
?private static Random rand =new Random();
?private String id;
?public FinalData(String id){this.id=id;}
?
?private final int VAL_ONE=9;
?private static final int VAL_TWO=99;//final的基本常量采用全部字母大寫,并且字與字時間用下劃線的形式
?
?private final int i4=rand.nextInt(20);
?static final int i5= rand.nextInt(20);
?
?private Value v1=new Value(11);
?private final Value v2=new Value(22);
?private static final Value v3=new Value(33);
?
?public String toString(){
??return id+": "+"i4= "+i4+", i5="+i5+" VAL_ONE= "+VAL_ONE;
?}
?
?public static void main(String[] args){
??FinalData fd1=new FinalData("fd1");
??
??//fd1.VAL_ONE++;? //不能修改final的基本數據類型
??//fd1.v2=new Value(22);//不能修改引用對象
??fd1.v2.i++;
??
??FinalData fd2=new FinalData("fd2");
??
??System.out.println(fd1);
??System.out.println(fd2);?
?}
}

打印結果:
fd1: i4= 10, i5=12 VAL_ONE= 9
fd2: i4= 13, i5=12 VAL_ONE= 9

結果表明,編譯時常量(在編譯時就能確定的final數據)和static final對象是不會改變的。
Java還允許在參數列表中以聲明的形式將參數指明為final的,如下
void with (final String s){
???……
}
說明在with函數中你可以讀s這個參數,但是不能改變它。

2.final函數
FinalMethod.java

class WithFinal{
?public final void f(){
??System.out.println("WithFinal.f()");
?}
}

public class FinalMethod extends WithFinal {
?public void f(){
??System.out.println("FinalMethod.f()");
?}
?
?public static void main(String[] args){
??
? FinalMethod fm=new FinalMethod();
??fm.f();
??
??WithFinal wf=new WithFinal();
??wf.f();
?}?
}

上面的代碼是不能通過編譯的,因為如果一個方法申明為final,那么繼承類就不能將其覆蓋。如果將繼承類的f()函數刪除,那么打印輸入如下:
WithFinal.f()
WithFinal.f()
即final想要確保在繼承中使方法行為保持不變,不會覆蓋。如果將final除掉,那么輸出為:
FinalMethod.f()
WithFinal.f()
即基類的方法被覆蓋,但基類的對象調用f()還是調用基類本身的函數,而不是繼承類的函數,這點要注意。

現在將final前面public改成private看看會發生什么情況:
wf.f()行報錯,說引用了private函數(說明wf引用對象調用的是基類的函數,而不是子類的f()),我們將此行注釋掉,結果通過了編譯,運行結果如下:
FinalMethod.f()
這是為什么呢?不是繼承類不能覆蓋基類的方法嗎?
答案:“覆蓋”只有在某方法使在基類的接口的一部分時才會出現,也就是說基類中的private方法并不是基類的接口,只是一些隱藏在類中的程序代碼而已。所以此時并沒有“覆蓋”f()方法,而是在子類中生成了一個新的方法而已。

3.final類
final類容易理解,當某個類定義為final時,則不能繼承此類。