final是一個java關鍵字,一個修飾符,可用於修飾變量,方法,修飾類.java
fianl最多見的用法時用來修飾成員變量,成員變量分爲靜態變量與普通變量. 對於final修飾的變量,不是不能被賦值,是其值不能被改變,能夠理解成只能賦一次值.能夠在定義時賦值,也能夠在定義後在另外賦值,但不管何種方式只能被賦值一次.數組
修飾靜態變量時,能夠選擇如下兩種方式賦值:函數
final static int a = 6; final static int b; static { b = 6; }
修飾普通成員變量時,能夠選擇如下三種方式賦值:this
public class test { int c = 1; int d; int e; { d = 2; } public test() { e = 3; } }
根據"靜態"不能訪問"非靜態"規則,就是說靜態的方法不能訪問非靜態成員,static初始化塊不能初始化非靜態成員,普通初始化塊也不能初始化靜態變量. 可是,有一個"bug"就是java容許經過方法訪問final成員,所以...有趣的事情發生了.code
public class test { final int a; { System.out.println(a);//這裏會報錯 printA(); a = 3; printA(); } void printA() { System.out.println(a); } public static void main(String[] args) { new test(); } }
以上這段代碼會報錯,由於java不容許final成員未初始化前訪問.對象
把上面那一行出錯的代碼註釋後...竟然經過了編譯?!blog
public class test { final int a; { //System.out.println(a);//這裏會報錯 printA(); a = 3; printA(); } void printA() { System.out.println(a); } public static void main(String[] args) { new test(); } }
printA()中只是用方法包裝了一下輸出函數,竟然就經過了編譯...有沒有興趣看一下結果?繼承
emmmmmm....final"默認值"爲0.....總之就不要想這些歪門邪道去在final初始化以前訪問final變量了 ,在使用final變量前初始化,初始化,初始化,重要的事情說三遍.圖片
final修飾局部變量其實也分兩種,一種是修飾形參,一種是修飾方法內部的局部變量內存
沒什麼好說的...就是形參的值不能改變.
public void f(final int a) { a = 3;//報錯. }
修飾局部變量時能夠定義時賦值,也能夠在定義後在賦值(僅一次).
public void f() { final int a = 3; final int b; b = 2; }
嗯.....這個是一個特別一點的例子,Talk is cheap.上代碼.
import java.util.Arrays; public class test { public static void main(String[] args) { final int[] arr = {1,2,3}; arr[1] = 5; Arrays.stream(arr).forEach(System.out::print); System.out.println(); final A a = new A(); a.setA(9); System.out.println(a.getA()); } } class A { private int a = 3; public void setA(int a) { this.a = a; } public int getA() { return a; } }
爲何final數組能夠賦值???fianl對象的值被改變了???看看結果:
final數組竟然被改變了??final對象的值也被改變了?? 其實呢,由於數組是引用類型,final修飾引用類型時,只能保證這個變量永遠"指向"那一段內存空間,保存的僅僅是一個引用,可是那段內存空間的值是能夠改變的.修飾對象時也是同樣的道理.
final修飾的方法不能被重寫,固然,不能"配合"private"使用",由於private把方法變成了私有,至關於對子類不可見,子類都不知道父類"還有這玩意",就能夠進行所謂的"重寫"了.
class A { private final void f(){} } class B extends A { public final void f(){}//沒毛病 }
由於B類的f()是屬於B類的,不是從A類繼承過來的.
final修飾類時表示該類不能被繼承.
final class A{} class B extends A{}//出錯
這是做者的公衆號,歡迎關注.