1. 程式人生 > >1.final關鍵字

1.final關鍵字

1.

首先補充一個地方:

class前面如果不加任何修飾符,則預設為default

顯示這段程式碼輸出結果:

分析這段程式碼:

輸出結果如下:

fd1:i4=15 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18

fd2:i4=13 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18

fd2:i4=1 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18


fd2:i4=1 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18

fd2:i4=9 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18

fd2:i4=8 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18

fd2:i4=0 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18
fd1:i4=15 ,INT_5 =  18

fd2:i4=2 ,INT_5 =  18

 

可以得知INT_5=18是一直不會去發生改變的,來看下是如何定義的:

再來看一下i4是如何定義的:

但是為什麼fd2的i4是一直變化的,但是fd1是一直不變的

永不改變的編譯常量:編譯期常量定義,根據慣例,即是static又是final域的也就是編譯期常量。

不能因為資料是final的就認為在編譯時可以知道他的值,執行時使用rand函式進行隨機生成數值進行初始化i4和INT_5就說明了這點;

在數值部分,也定義了靜態和非靜態的區別:

次區別只有在數值執行時被初始化後才會被顯現,static是靜態的,因此因此INT_5的值是唯一的,是不可以通過建立第二個finaldata物件而加以改變的,因為他是static的,在裝載時已經被初始化的了,但是不是每次建立物件時都會進行初始化操作。

v1到vAL_3說明了final的引用意義,

不能因為v2是final的,就認為他是無法改變他的值,他是一個引用,final意味著無法將v2再次指向一個新的物件:

陣列定義如下:

其中a是陣列物件:

由此可以得知final是可以改變的但是不可以指向新的物件,佐證如下:

final定義的變數可以在同一個物件的情況下被改變,但是如果換了一個物件,那麼就是不能再賦予新的值的,作用域是一個物件內部,

但是作用域即是static又是final的則是編譯產量,因此是存在於整個生命週期的,不可以輕易被改變的。

完整驗證程式碼如下,可以複製拿去驗證:

import java.util.Random;

public class finalData {
    private static Random rand=new Random(47);
    private String id;
    public finalData(String id){  // 定義一個構造方法
     this.id=id;
    }
    private final int Valueone=9;
    private static final int VALUE_TWO=99;
    //以上兩個都帶有final,因此可以用作編譯期常量,區別並不是很大
    private static final int VALUE_THREE=39;
    /**上面一行是常用的用於定義編譯期常量的寫法,定義為public表示可以為包之外所用,
     * 定義為static,則強調只有一份
     * 定義為final,則說明他是一個常量
     * 帶有恆定初始值也就是編譯常量:
     * 根據慣例,編譯常量也就是即是final域又是static域的。
     */
    private final int i4=rand.nextInt(20);
    static final int INT_5=rand.nextInt(20);
    private Value v1=new Value(11);
    private final Value v2=new Value(22);
    private static  final  Value v3=new Value(33);
    private final int[] a={1,2,3,4,5,6,7};
    public String toString(){
        return id+":"+"i4="+i4+" ,INT_5 =  "+INT_5;
    }
    public static void main(String[] args){
   finalData fd1=new finalData("fd1");
   //fd1.Valueone++;//呼叫的時候發現會有錯誤,  private final int Valueone=9;
        fd1.v2.i++;//將i中值自增1,看看是否會變成23
        fd1.v1=new Value(9);//看下將v1的引數從11改成9會不會成功   private Value v1=new Value(11);//這個可以的執行無錯誤
        for(int i=0;i<fd1.a.length;i++){//取fd1類中陣列的長度作為迴圈的次數
            fd1.a[i]++; //物件的持續性變化
            System.out.println("驗證fd1.a[i]++等於  =="+fd1.a[i]++);
//            fd1.v2=new Value(0); //Error:(28, 16) java: 無法為最終變數v2分配值
//            fd1.v3=new Value(1); //Error:(29, 16) java: 無法為最終變數v3分配值
//            fd1.a=new int[3]; //Error:(30, 16) java: 無法為最終變數a分配值
            System.out.println(fd1);
            System.out.println(fd1);
        finalData fd2=new finalData("fd2");
            System.out.println(fd1);
            System.out.println(fd2);
        }

    }
}