欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入淺出的講解Java關鍵字final的作用

 更新時間:2023年06月06日 11:54:37   作者:alexhilton  
final是Java中非常常見的一個關鍵字,可以說每天都在使用它,雖然常見,但卻也不見得都那么顯而易見,今天就來研究一下final,以加深對它的理解和更合理的運用,需要的朋友可以參考下

final可以用來干什么

修飾類

當一個類不想被繼承時,就可以用final來修飾。

修飾方法

當一個方法不想被子類覆寫(Override)時,可以用final來修飾。另外一方面,把方法用final來修飾也有一定的性能提升上的幫助,因為虛擬機知道它不會被覆寫,所以可以以更簡單的方式來處理。

private的方法,默認都會被編譯器加上final.

修飾變量

被final修飾的變量只能賦值一次,之后不能再被修改。如:

final int a = 10;
a = 4; // compilation error

需要注意的是,這里說的是只能賦值一次,并不意味著,非要在聲明變量時直接初始化,比如,下面的代碼也是完全合法的:

final int a;
if (foo()) {
    a = 3;
} else {
    a = 4;
}

修飾域變量

域變量也是變量,所以用final來修飾的第一個作用就是賦值后,不能再修改變量的值,比如:

final int a = 10;
final Object b = new Object();

對于基本類型來說,就是變量值不能再被修改;對于引用來說,就是不能再讓其指向其他對象或者null。

但對于域變量,聲明為final的域變量必須在聲明時初始化,或者在構造方法中初始化,否則會有編譯錯誤。

此外,聲明為final的域變量還有內(nèi)存模型上的語義,下面詳細說

內(nèi)存模型的作用--防止變量從構造方法中逸出

這個主要是針對被final修飾的域變量,虛擬機會有禁止指令重排的保證:

  • 在構造方法內(nèi)對一個final變量的寫入,與隨后這個被構造對象的引用賦值給一個引用變量,這二個順序不改變,final變量的寫入一定要早于對象引用的賦值。

什么意思呢?在多線程環(huán)境下,域變量是有可能從構造方法中逸出的,也就是說線程有可能讀到還沒有被構造方法初始化的域變量的值。比如:

class Foo {
    int a;
    Foo(int v) {
        a = v;
    }
}

如果是在多線程環(huán)境下,一個線程A在創(chuàng)建Foo的對象,另一個線程B在讀對象的a的值,則B是有可能讀到未正確初始化a的值(默認初始值0)。這就是域變量從構造方法中逸出。

關鍵字final可以禁止虛擬機指令重排,從而保證了構造方法執(zhí)行完畢前final修飾的變量一定是初始化過了的。

匿名內(nèi)部類使用外部變量時為何要強制使用final修飾

這個大家肯定都習以為常了,比如

private void initViews() {
    final int a = 3; // Compilation error if remove final
    btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (a > 1) {
                // volala
            }
        }
    }
}

那么,有沒有想過為什么?而像其他支持完整閉包的語言如JavaScript,Python等,是沒有這等限制的。究其原因,是Java對閉包支持不夠完整,或者說它并不是像動態(tài)語言那樣的完整閉包。對于匿名內(nèi)部類來說,編譯器會創(chuàng)建一個命名類(OutClass$1之類的),然后把匿名類所在的能捕獲的變量,以構造參數(shù)的形式傳遞給內(nèi)部類使用,這樣一樣,外部的變量與內(nèi)部類看到的變量是不同的,雖然它們的值是相同的,因此,如果再允許外部修改這些變量,或者內(nèi)部類里面修改這些變量,都會造成數(shù)據(jù)的不一致性(因為它們是不同的變量),所以Java強制要求匿名內(nèi)部類訪問的外部變量要加上final來修飾。

對于其他語言,匿名內(nèi)部類,持有的是外部變量的一個包裝的引用(wrapper reference),這可以能看不懂,但是理解起來就是內(nèi)部類能直接訪問外部變量,外部與閉包內(nèi)部訪問的是同一個變量,因此外部修改了,內(nèi)部能看到變化,內(nèi)部修改了,外部也能看到變化。

一句話總結就是,Java內(nèi)部類與外部持有的是值相同的不同的變量;其他支持閉包的語言則持有的是相同的變量。

建議能使用final的地方就加上final修飾

最后來聊聊,啥時候應該用final呢?孤的建議(以及眾多大師的建議)就是能多用就多用,除非不能用final,否則就用。原因,有這么幾條:

  • 域變量盡可能加上final

    這個原因比較明確,前面也提到了,在多線程條件下,會有很大的優(yōu)勢。盡可能加上final來修飾域變量,甚至用Immutable Object,可以省去構造時的多線程同步。

    多線程最大的麻煩是狀態(tài)同步,啥是狀態(tài)?其實就是共享數(shù)據(jù),域變量就是共享數(shù)據(jù),所以,如果共享數(shù)據(jù)都是不可變的(Immutable),那么自然就沒有了同步上的麻煩。

  • final類和方法能提升性能

    正常的類和方法,虛擬機需要為了繼承和方法覆寫而做一次準備,如果加上了final,虛擬機知道它不會被繼承或者覆寫,那么就可以做一些優(yōu)化。雖然,這并不顯著,但是還是可以提升一些性能的。

  • final變量能提升可讀性

    無論是域變量還是本地變量,加上了final修飾,程序的維護者就知道了,這個變量的值不會再改變,這無疑會大大增加可讀性。

以上就是深入淺出的講解Java關鍵字final的作用的詳細內(nèi)容,更多關于Java 關鍵字 final的資料請關注腳本之家其它相關文章!

相關文章

  • springdata jpa使用Example快速實現(xiàn)動態(tài)查詢功能

    springdata jpa使用Example快速實現(xiàn)動態(tài)查詢功能

    這篇文章主要介紹了springdata jpa使用Example快速實現(xiàn)動態(tài)查詢功能,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Springboot自定義注解&傳參&簡單應用方式

    Springboot自定義注解&傳參&簡單應用方式

    SpringBoot框架中,通過自定義注解結合AOP可以實現(xiàn)功能如日志記錄與耗時統(tǒng)計,首先創(chuàng)建LogController和TimeConsuming注解,并為LogController定義參數(shù),然后,在目標方法上應用這些注解,最后,使用AspectJ的AOP功能,通過切點表達式定位這些注解
    2024-10-10
  • java實現(xiàn)微信小程序加密數(shù)據(jù)解密算法

    java實現(xiàn)微信小程序加密數(shù)據(jù)解密算法

    這篇文章主要為大家詳細介紹了java實現(xiàn)微信小程序加密數(shù)據(jù)解密算法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-09-09
  • java調(diào)用中國天氣網(wǎng)api獲得天氣預報信息的方法

    java調(diào)用中國天氣網(wǎng)api獲得天氣預報信息的方法

    這篇文章主要介紹了java調(diào)用中國天氣網(wǎng)api獲得天氣預報信息的方法,可實現(xiàn)調(diào)用溫度、風力風向及近期天氣狀況等功能,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • Spring中的BeanFactory工廠詳細解析

    Spring中的BeanFactory工廠詳細解析

    這篇文章主要介紹了Spring中的BeanFactory工廠詳細解析,Spring的本質(zhì)是一個bean工廠(beanFactory)或者說bean容器,它按照我們的要求,生產(chǎn)我們需要的各種各樣的bean,提供給我們使用,需要的朋友可以參考下
    2023-12-12
  • Java文件分級目錄打包下載zip的實例代碼

    Java文件分級目錄打包下載zip的實例代碼

    這篇文章主要介紹了Java文件分級目錄打包下載zip的實例代碼,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • java簡單操作word實例

    java簡單操作word實例

    這篇文章主要為大家詳細介紹了java簡單操作word實例,感興趣的朋友可以參考一下
    2016-03-03
  • Java實現(xiàn)生成pdf并解決表格分割的問題

    Java實現(xiàn)生成pdf并解決表格分割的問題

    這篇文章主要為大家詳細介紹了如何利用Java實現(xiàn)生成pdf,并解決表格分割的問題,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-11-11
  • Java 高并發(fā)三:Java內(nèi)存模型和線程安全詳解

    Java 高并發(fā)三:Java內(nèi)存模型和線程安全詳解

    本文主要介紹Java高并發(fā)內(nèi)存模型和線程安全的資料,這里整理詳細的資料及1.原子性 2.有序性 3.可見性 4.Happen-Before 5.線程安全的概念,有需要的小伙伴可以參考下
    2016-09-09
  • java  基礎知識之IO總結

    java 基礎知識之IO總結

    這篇文章主要介紹了java 基礎知識之IO總結的相關資料,Java中的I/O分為兩種類型,一種是順序讀取,一種是隨機讀取,需要的朋友可以參考下
    2017-03-03

最新評論