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);
}
}
}