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

Java中的關(guān)鍵字之final詳解

 更新時間:2024年01月02日 09:04:33   作者:luffylv  
這篇文章主要介紹了Java中的關(guān)鍵字之final詳解,final關(guān)鍵字算是個高頻的java基礎(chǔ)問題了,面試官可能會問說說final,final修飾的抽象類能夠被繼承嗎等等,下面匯總關(guān)于final關(guān)鍵字的知識點,需要的朋友可以參考下

一、final關(guān)鍵字概述

final有最終的、不可變更的意思,它可用于修飾類、變量和方法。用于表示它修飾的類、方法和變量不可改變。

總結(jié)起來是如下三點:

  • final修飾變量——表示該變量一旦獲得了初始值就不可被改變,即不能夠被重新賦值。final即可以修飾成員變量(包括類變量和實例變量),也可以修飾局部變量形參。
  • final修飾方法——final修飾的方法不可被重寫。
  • final修飾類——final修飾的類不可以被繼承。

二、final修飾變量

1、final修飾成員變量

Java語法規(guī)定:final修飾的成員變量必須由程序員顯示地指定初始值。

final修飾的類變量、實例變量能指定初始值的地方如下:

  • 類變量:必須在靜態(tài)初始化塊中指定初始值或聲明該類變量時指定初始值,而且只能在這兩個地方的其中之一指定。
  • 實例變量:必須在普通初始化塊、聲明該實例變量或構(gòu)造器中指定初始值,而且只能在三個地方的其中之一指定。

若成員變量的值未在上面任何一處指定初始值,那么這些成員變量的值將一直是系統(tǒng)默認分配的0、'\u0000'、false或null,這些成員變量也就完全失去了存在的意義。

final修飾成員變量的例子如下:

public class FinalVariable {
    // 定義成員變量時指定默認值
    final int a = 2;
    final String str;
    final int b;
    final static float c;
    // 在普通初始化塊中,給沒有指定默認值的實例變量指定初始值
    {
        str = "final";
        // 聲明實例變量a時已經(jīng)指定了默認值,因此不能為a重新賦值
        // a = 66;
    }
    // 在靜態(tài)初始化塊中,給沒有指定默認值的類變量指定初始值
    static {
        c = 6.6f;
    }
    // 在構(gòu)造器中,可對沒有指定默認值,有沒有在普通初始化中
    // 指定初始值的實例變量指定初始值
    public FinalVariable() {
        b = 8;
        // 已在普通初始化塊中為str指定了初始值,因此在構(gòu)造器中不能對str重新賦值
        // str = "change";
    }
    public void change() {
        // 不能再普通方法中為final修飾的成員變量指定初始值,也不能重賦值
        // c = 8.8f;
    }
}

2、final修飾局部變量

系統(tǒng)不會對局部變量進行初始化,局部變量必須被顯示初始化。因此使用final修飾局部變量時,即可以在定義時指定默認值,也可以不指定默認值。如果在定義時沒有指定默認值,則可以在后面代碼中對該final變量賦初始值,但只能一次,不能重復(fù)賦值;如果在定義時已經(jīng)指定默認值,則后面代碼中不能再對該變量賦值。

final修飾局部變量的例子如下:

public class FinalLocalVariable {
    // 不能對final修飾的形參賦值
    public void test(final int a) {
        // 因為形參在調(diào)用該方法時,已經(jīng)由系統(tǒng)根據(jù)傳入的參數(shù)來完成初始化,
        // 因此使用final修飾的形參不能被賦值。
        // a = 6;
    }
    public static void main(String[] args) {
        // 定義final局部變量時指定默認值,則str變量無法重新賦值
        final String str = "final";
        // 定義final局部變量時沒有指定默認值,則該局部變量可被賦值一次
        final int b;
        b = 8;
    }
}

3、final修飾基本類型變量和引用類型變量的區(qū)別

當(dāng)使用final修飾基本類型變量時,不能對基本類型變量重新賦值,因此基本類型變量不能被改變。但對于引用類型變量而言,它保存的僅僅是一個引用,final只保證這個引用變量所引用的地址不會改變,即一直引用同一個對象,但可以改變引用類型變量所引用的對象的內(nèi)容。

下面以final修飾數(shù)組和Person對象舉例:

import lombok.Data;
import java.util.Arrays;
@Data
class Person {
    private int age;
    public Person(int age) {
        this.age = age;
    }
}
public class FinalReference {
    public static void main(String[] args) {
        // final修飾數(shù)組變量,iArr是一個引用變量
        final int[] iArr = {5, 6, 12, 9};
        System.out.println(Arrays.toString(iArr));
        // 對數(shù)組元素進行排序
        Arrays.sort(iArr);
        System.out.println(Arrays.toString(iArr));
        // 對數(shù)組元素賦值
        iArr[2] = -8;
        System.out.println(Arrays.toString(iArr));
        // 不能對iArr重新賦值
        // iArr = null;
        // final修飾Person變量,p是一個引用變量
        final Person p = new Person(45);
        // 改變Person對象的age實例變量
        p.setAge(23);
        System.out.println(p.getAge());
        // 不能對p重新賦值
        // p = null;
    }
}

4、final變量的“宏替換”

final修飾符的一個重要用途就是定義“宏變量”。對一個final變量來說,不管它是類變量、實例變量還是局部變量,只要該變量滿足三個條件,這個final變量就不再是一個變量,而是相當(dāng)于一個直接量。

  1. 使用final修飾符修飾;
  2. 在定義該final變量時指定了初始值(該初始值可以是直接量,也可以是基本的算數(shù)表達式或字符串連接運算,不可以是普通變量或調(diào)用方法);
  3. 該初始值可以在編譯時就被確定下來。

滿足以上三個條件的final變量本質(zhì)上就是一個“宏變量”,編譯器會把程序中所有用到該變量的地方直接替換成該變量的值。

下面看下final變量作為“宏變量”的例子:

上面代碼a是final修飾的局部變量,并且在定義時指定了初始值5,對于程序來說,變量a其實根本不存在,實際上編譯器在編譯階段,將System.out.println(a);轉(zhuǎn)換為System.out.println(5);。

final變量的b和str1在定義分別通過基本的算數(shù)表達式和字符串連接運算指定了初始值。因此b和str1是“宏變量”。由于str1是“宏變量”,它將被直接替換成“final宏變量888”,str1將指向的是字符串常量池中的“final宏變量888”。因此第一個判斷為true。而str2需要調(diào)用String類的方法,因此編譯器無法在編譯時確定str2的值,str2不會被當(dāng)成“宏變量”處理。因此第二個判斷為false。

s2變量引用的字符串可以在編譯時就確定下來,因此時直接引用常量池中已有的“final宏變量”。因此第三個判斷相等。對于s3而言,它的值由st1和st2進行連接運算后得到。由于st1、st2只是兩個普通變量,編譯期不會執(zhí)行“宏替換”,因此編譯器無法在編譯時確定s3的值,也就無法讓s3指向字符串常量池中緩存的“final宏變量”,所以第4個判斷為false。而s4是由st3和st4進行連接運算后得到,st3和st4是兩個宏變量,因此可以執(zhí)行“宏替換”,編譯器可以編譯階段確定s4的值,使其指向字符串常量池中緩存的“final宏變量”,所以第5個判斷為true。實際上s2和s4是等價的。

三、final修飾方法

 final修飾的方法不可被重寫,如果出于某些原因,不希望子類重寫父類某個方法,則可以使用final修飾該方法。

Java提供的Object類里就有一個final方法:getClass(),因為Java不希望任何類重寫這個方法,所以使用final把這個方法密封起來。但對于該類提供的toStirng()和equals()方法,都允許子類重寫,因此沒有使用final修飾他們。

四、final修飾類

final修飾的類不可以有子類,例如java.lang.Math類就是一個final類,他不可以有子類。

當(dāng)子類繼承父類時,將可以訪問到父類內(nèi)部數(shù)據(jù),并可以通過重寫父類方法來改變父類方法的實現(xiàn)細節(jié),這可能導(dǎo)致一些不安全的因素。為了保證某個類不可被繼承,則可以使用final修飾這個類。

到此這篇關(guān)于Java中的關(guān)鍵字之final詳解的文章就介紹到這了,更多相關(guān)final關(guān)鍵字內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解決Java編譯時錯誤:A JNI error has occurred,please check your installation and try again

    解決Java編譯時錯誤:A JNI error has occurred,ple

    這篇文章主要介紹了解決Java編譯時錯誤:A JNI error has occurred,please check your installation and try again,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • 詳解path和classpath的區(qū)別

    詳解path和classpath的區(qū)別

    這篇文章主要介紹了詳解path和classpath的區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • Maven中resources標(biāo)簽的用法詳解

    Maven中resources標(biāo)簽的用法詳解

    本文主要介紹了Maven中resources標(biāo)簽的用法詳解,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • JVM要雙親委派的原因及如何打破它

    JVM要雙親委派的原因及如何打破它

    平時做業(yè)務(wù)開發(fā)比較少接觸類加載器,但是如果想深入學(xué)習(xí),了解類加載的原理是必不可少的.java的類加載器有哪些?什么是雙親委派?為什么要雙親委派?如何打破它?接下來本文就帶大家詳細介紹這些知識 ,需要的朋友可以參考下
    2021-06-06
  • 解析spring-security權(quán)限控制和校驗的問題

    解析spring-security權(quán)限控制和校驗的問題

    這篇文章主要介紹了解析spring-security權(quán)限控制和校驗的問題,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • springMVC導(dǎo)出word模板的方法

    springMVC導(dǎo)出word模板的方法

    這篇文章主要為大家詳細介紹了springMVC導(dǎo)出word模板的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • 詳解JAVA中使用FTPClient工具類上傳下載

    詳解JAVA中使用FTPClient工具類上傳下載

    這篇文章主要介紹了JAVA中使用FTPClient工具類上傳下載的相關(guān)資料,java 使用FTP服務(wù)器上傳文件、下載文件,需要的朋友可以參考下
    2017-08-08
  • java怎么連接并訪問activemq

    java怎么連接并訪問activemq

    這篇文章主要介紹了java怎么連接并訪問activemq,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-07-07
  • SpringBoot項目使用mybatis-plus逆向自動生成全套代碼

    SpringBoot項目使用mybatis-plus逆向自動生成全套代碼

    在JavaWeb工程中,每一個SSM新項目或者說是SpringBoot項目也好,都少不了model、controller、service、dao等層次的構(gòu)建。使用mybatis-plus逆向可以自動生成,感興趣的可以了解一下
    2021-09-09
  • Spring Boot 整合 Druid過程解析

    Spring Boot 整合 Druid過程解析

    這篇文章主要介紹了Spring Boot 整合 Druid過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11

最新評論