深入Java Final

來源:互聯網
上載者:User

JAVA關鍵字final用於修飾資料、方法或類,通常意味著“無法改變的”,既資料不能改變,方法不能覆蓋,類不能繼承。一般採用final有兩種原因:設計和效率。而隨著JAVA版本的更新,一些效率上的問題可以交由編譯器和JVM處理。因此,採用final來解決效率問題就顯得不是那麼重要了。

Final修飾符大多運用於基礎資料型別 (Elementary Data Type)(primitive)域或者不可變(immutable)類的域(如果類中的所有方法方法都不會改變其對象,這種類就是不可變類。String就是一個不可變類)。

【final資料】

Final關鍵字用修飾資料主要有兩種情況:

1. 編譯期常量

2. 運行時初始化的值

對於編譯期常量,指的是一個既是final又是static的域(依照慣例,編譯期常量全部用大寫字母命名,並且用底線分隔各個單詞),它只佔據一段不能改變的儲存空間。編譯器可以將編譯期常量代入到任何可能用到它的計算式中,也就是說,可以在編譯時間執行計算式,這相對減輕了運行時負擔。編譯期常量在定義時必須對它賦值(不一定是基本類型)。

運行時初始化的值,對於基本類型,final使得其值不可改變;而對於對象引用,final使得引用不可改變,即無法將其改為指向另一個對象,然而,對象本身卻可以修改(適用於數組,數組也是對象)。

複製代碼 代碼如下:public class javaFinalData{

private static final String TESTD = "test";
public static final String TESTE = "test";
public static final String[] TESTF = {"1","2"}; //非基本類型
private static final String[] TESTG = new String[2];

public static void main(String args[]){
final int testA = 1;
final String testB = "test";
final int[] testC = {1,1,2,};
System.out.println(testC[1]);
testC[1] = 123;
System.out.println(testC[1]);
}
}

【未賦值的final域】

JAVA允許產生未賦值的final域,但是必須在域的定義處或者每個構造器中對final域進行賦值(有多少個構造器就必須賦值幾次),確保在使用前被初始化。採用這種方式,可以使得final運用得更加靈活,在同一個類中,根據不同的對象賦予不同的值,卻又保持不可改變的特性。

複製代碼 代碼如下:public class javaBlankFinal{
private final int blank;

public javaBlankFinal(){
blank = 2011;
}

public javaBlankFinal(int temp){
blank = 2012;
}

public javaBlankFinal(String temp){
blank = 2014;
}

public static void main(String args[]){
new javaBlankFinal();
}
}

【final方法】

使用final方法有兩方面原因:一是將方法鎖定,防止方法被覆蓋,確保在繼承中方法行為保持不變;二是將方法調用轉為內聯調用(inlining),以減少方法調用的開銷。但是,在最近的版本中,JVM可以自行進行最佳化,因此無需使用final方法來處理效率問題。

關於final方法,還有一點需要注意,類中所有的private方法都隱式地指定為final方法(也可以為其加上final修飾,但沒有意義)。當你試圖覆蓋一個private方法,編譯器並沒有報錯,但是,實際上你並沒有覆蓋該方法,只是產生了一個新方法。因為private方法是無法被外部類所訪問的,當然就無法覆蓋到它了。

使用@Override註解可以防止上述問題。如程式所示:

複製代碼 代碼如下:class finalFunction{
private void finalFunctionA(){
System.out.println("finalFunctionA");
}

private final void finalFunctionB(){
System.out.println("finalFunctionB");
}

final void finalFunctionC(){
System.out.println("finalFunctionC");
}

void functionD(){}
}

class overrideFinalFunction extends finalFunction{
//@Override 添加@Override註解可以識別是否是override
public void finalFunctionA(){
System.out.println("override finalFunctionA");
}

public final void finalFunctionB(){
System.out.println("override finalFunctionB");
}

//final void finalFunctionC(){} //Cannot override the final method from finalFunction

@Override
void functionD(){} //真正的override方法
}

public class javaFinalFunction extends finalFunction{
public static void main(String args[]){
finalFunction ff = new finalFunction();
//ff.finalFunctionA(); //無法調用private方法
//ff.finalFunctionB();

overrideFinalFunction off = new overrideFinalFunction();
off.finalFunctionA(); //public方法
off.finalFunctionB();
}
}

【final類】

使用final類一般是出於設計原因,不允許該類被繼承。這樣可以保證類的行為不會改變,或許還能避免一些安全危機。Final類中所有的方法都隱式指定為final方法,因此無法被覆蓋(因為final類禁止繼承,也就無法覆蓋其類中的方法)。在Java核心API中,有許多應用final的例子,例如java.lang.String。為String類指定final防止覆蓋length()等方法。

對於final域來說,即使將一個類聲明為final,類中的域不會自動成為final域。

複製代碼 代碼如下:final class finalClass{
int testA = 2011;
}
//class extendFinalClassextends finalClass{} //can not extendthe final class finalClass

public class javaFinalClass{
public static void main(String args[]){
finalClass fc = new finalClass();
System.out.println(fc.testA);
fc.testA = 2012;
System.out.println(fc.testA);
}
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.