程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 聊聊Java的final關鍵字,javafinal關鍵字

聊聊Java的final關鍵字,javafinal關鍵字

編輯:JAVA綜合教程

聊聊Java的final關鍵字,javafinal關鍵字


Java的final關鍵字在日常工作中經常會用到,比如定義常量的時候。如果是C++程序員出身的話,可能會類比C++語言中的define或者const關鍵字,但其實它們在語義上差距還是挺大的。

在Java中,final可以用來修飾類、方法和變量(包括成員變量和局部變量)。我們先來簡單介紹一下final關鍵字的這幾個用法。

一、final修飾類

常見的一個例子就是String類。當用final修飾一個類時,表明這個類不能被繼承,並且final類中的所有成員方法都會被隱式地指定為final方法,但成員變量不會變。

一般來說,我們還是盡量不要將類設計為final類,除非我們出於某些因素的考慮必須這麼做。比如不希望類被繼承,也就是說不希望類被修改語義。如果我們繼承String類,那麼就可以定義一個可被修改的String類,這對於String類的使用者來說近乎是一種災難。

二、final修飾方法

使用final修飾方法有兩個原因:

  1. 是把方法鎖定,以防任何繼承類修改它的含義;

  2. 是效率。在早期的Java實現版本中,會將final方法轉為內嵌調用。但是如果方法過於龐大,可能看不到內嵌調用帶來的任何性能提升。在最近的Java版本中,不需要使用final方法進行這些優化了。

同final類相似,只有在想明確禁止該方法在子類中被覆蓋的情況下才將方法設置為final。另外,類的private方法會隱式地被指定為final方法,其語義要求private方法不能被重新定義。

三、final修飾變量

final用得最多的地方就是修飾變量。對於一個final變量,如果是基本數據類型的變量,則其數值一旦在初始化之後便不能更改;如果是引用類型的變量,則在對其初始化之後便不能再讓其指向另一個對象,但是它指向的對象的內容是可變的。

由於final變量初始化之後無法修改,針對這個特性,Java編譯器對此進行了優化。當final變量是基本數據類型以及String類型時,如果在編譯期間能知道它的確切值,則編譯器會把它當做編譯期常量使用。這個優化通常對於程序邏輯沒有太多影響,但如果用==比較的時候,可能會出乎意料。具體可以參考之前的文章《Java自動裝箱和拆箱》。

綜上所述,final在修飾類和方法時,代表不能再修改其定義,而在修飾變量時,則類似C++中的const關鍵字,用於表示常量。

一個好的編程習慣是我們應該盡量將變量聲明為final的,除非變量必須是可變的。例如當你在方法中不需要改變作為參數的變量時,可以使用final進行聲明,這樣可以防止你無意的修改,尤其是當你的方法很長很復雜的時候。當然是否用final修飾參數,都不會影響方法之外的變量。

使用final關鍵字還有個好處,是它能確保初始化過程的安全性,可以不受限制的訪問不可變對象,並在多線程共享這些對象時無須同步。當我們有多個基本類型的變量,他們之前需要保持數據一致的時候,通常的辦法是使用synchronized關鍵字來保證對這些變量操作的原子性。如果使用final關鍵字,我們可以定義新類,包含這些變量(用final修飾),這樣這些變量就成了常量,變量修改操作就成了賦值操作(是原子操作),這樣就避免了使用加鎖同步。當然不可修改的變量也會導致很多小對象的生成,加重垃圾回收的負擔,相較而言可以忽略了。

最後,我們知道,在匿名內部類的方法參數只能訪問final類型的局部變量,編譯器也強制要求這一點,這是為什麼呢?其根本原因在於局部變量的生命周期與匿名內部類對象的生命周期不一致。局部變量所在的方法執行完之後,匿名內部類對象仍然存在,這時匿名內部類對象就無法訪問到該局部變量,因為該局部變量的生命周期已經結束。使用final修飾局部變量,其實是將局部變量“復制”了一份,復制品直接作為局部內部中的數據成員,這樣就解決的生命周期不一致的問題。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved