Java基礎(chǔ)-面向?qū)ο?final關(guān)鍵字

Java工程師知識樹 / Java基礎(chǔ)


1齐媒、final關(guān)鍵字作用

final可以修飾類蒲每、方法、變量喻括。那么分別是什么作用呢邀杏?

(1)修飾類:表示類不可被繼承

(2)修飾方法:表示方法不可被覆蓋

(3)修飾變量:表示變量一旦被賦值就不可以更改它的值。java中規(guī)定final修飾成員變量必須顯示指定變量的值唬血。

2望蜡、final關(guān)鍵字修飾類

final關(guān)鍵字修飾類表示這個(gè)類是不可被繼承的.

3、final關(guān)鍵字修飾方法

final修飾的方法不能被重寫,但是可以重載拷恨。

下面給出了一個(gè)代碼例子脖律。

主要注意的是:父類中private的方法,在子類中不能訪問該方法腕侄,但是子類與父類private方法相同的方法名小泉、形參列表和返回值的方法芦疏,不屬于方法重寫,只是定義了一個(gè)新的方法微姊。

class ClassFinal3{
    private void testClassFinalMethod(){};
}
// 實(shí)現(xiàn)final修飾的接口
class InnerClass4 extends ClassFinal3 {
    void testClassFinalMethod(){};
}

使用final方法的原因有兩個(gè):

  • 第一個(gè)原因是把方法鎖定酸茴,以防任何繼承類修改它的含義;
  • 第二個(gè)原因是效率柒桑。在早期的Java實(shí)現(xiàn)版本中弊决,會將final方法轉(zhuǎn)為內(nèi)嵌調(diào)用。但是如果方法過于龐大魁淳,可能看不到內(nèi)嵌調(diào)用帶來的任何性能提升(現(xiàn)在的Java版本已經(jīng)不需要使用final方法進(jìn)行這些優(yōu)化了)飘诗。

類中所有的private方法都隱式地指定為final。

4界逛、final關(guān)鍵字修飾變量

(1)修飾成員變量

  • 如果final修飾的是類變量昆稿,只能在靜態(tài)初始化塊中指定初始值或者聲明該類變量時(shí)指定初始值。
  • 如果final修飾的是成員變量息拜,可以在非靜態(tài)初始化塊溉潭、聲明該變量或者構(gòu)造器中執(zhí)行初始值。

(2)修飾局部變量

系統(tǒng)不會為局部變量進(jìn)行初始化少欺,局部變量必須顯示初始化喳瓣。因此使用final修飾局部變量時(shí),即可以在定義時(shí)指定默認(rèn)值(后面的代碼不能對變量再賦值)赞别,也可以不指定默認(rèn)值畏陕,而在后面的代碼中對final變量賦初值(僅一次)

實(shí)例:

package com.jvm.study;

public class FinalVar {
    final static int a = 0;//再聲明的時(shí)候就需要賦值
    public static void main(String[] args) {
        final int localA;   //局部變量只聲明沒有初始化仿滔,不會報(bào)錯(cuò),與final無關(guān)惠毁。
        localA = 0;//在使用之前一定要賦值
        localA = 1; // 但是不允許第二次賦值 Variable 'localA' might already have been assigned to
        a = 1;// Cannot assign a value to final variable 'a'
    }
}

(3)修飾基本類型數(shù)據(jù)和引用類型數(shù)據(jù)

  • 如果是基本數(shù)據(jù)類型的變量,則其數(shù)值一旦在初始化之后便不能更改崎页;
  • 如果是引用類型的變量鞠绰,則在對其初始化之后便不能再讓其指向另一個(gè)對象。但是引用的值是可變的飒焦。

使用示例

package com.jvm.study;

public class FinalReferenceTest {
    public static void main() {
        final int[] iArr = {1, 2, 3, 4};
        iArr[2] = -3;//合法 
        iArr = null;//非法蜈膨,對iArr不能重新賦值 Cannot assign a value to final variable 'iArr'

        final Person p = new Person(25);
        p.setAge(24);//合法
        p.setAge(12);//合法
        p = null;//非法  Cannot assign a value to final variable 'p'
    }

    static class Person {
        private int Age;
        Person(int Age) {
            this.Age = Age;
        }
        public int getAge() {
            return Age;
        }
        public void setAge(int age) {
            Age = age;
        }
    }

}

5、與Static關(guān)鍵字

static簡介

static是靜態(tài)修飾符牺荠,一般修飾成員翁巍。

被static修飾的成員屬于類,不屬于單個(gè)這個(gè)類的某個(gè)對象志电。static修飾的成員被多個(gè)對象共享曙咽。static修飾的成員屬于類蛔趴,但是會影響每一個(gè)對象挑辆。被static修飾的成員又叫類成員例朱,不叫對象的成員。

注意:static不能修飾類 構(gòu)造方法 局部變量鱼蝉。

成員變量使用

使用不同類中的成員變量有以下幾種方式:

  • (1) 創(chuàng)建該類對象洒嗤,使用對象調(diào)用
  • (2) 繼承,使用super調(diào)用
  • (3) 使用類名直接調(diào)用魁亦,調(diào)用格式:類名.靜態(tài)成員變量名

stati修飾成員變量的注意事項(xiàng)

  • (1)靜態(tài)方法可以直接訪問類變量和靜態(tài)方法渔隶。
  • (2) 靜態(tài)方法不能直接訪問非靜態(tài)成員變量或成員方法。非靜態(tài)成員方法可以直接訪問類變量或靜態(tài)方法洁奈。
  • (3) 靜態(tài)方法中间唉,不能使用this關(guān)鍵字。

static和final聯(lián)合使用

  • static和final可以修飾成員變量和成員方法利术,對于變量呈野,可理解為“全局變量”,一旦賦值印叁,不能被修改被冒,可通過類名訪問;對于方法轮蜕,不能被子類覆蓋昨悼,可通過類名訪問。
  • private 方法默認(rèn)均為 final 方法.
  • final 常常和 static, public 配合來修飾一個(gè)實(shí)例變量跃洛,表示為一個(gè)全類公有的公開靜態(tài)常量率触。

6、不變模式

關(guān)于 final 的設(shè)計(jì)模式: 不變模式

  • 1税课、不變模式: 一個(gè)對象一旦產(chǎn)生就不可能再修改(String 就是典型的不變模式)闲延;通過不變模式可以做到對象共享;

  • 2韩玩、池化思想: 用一個(gè)存儲區(qū)域來存放一些公用資源以減少存儲空間的開銷垒玲。

    有池的類型:boolean,byte,int,short,long,char,(池范圍在-127~128之間)(float,double 等小數(shù)沒有池)
    例: 在String類中有個(gè)串池(在代碼區(qū))。
    池: 堆里的一片獨(dú)立空間找颓。目的是拿空間換時(shí)間合愈,讓運(yùn)算效率更高。

    • 如果用Stirng str = "abc" 來創(chuàng)建一個(gè)對象時(shí)击狮,則系統(tǒng)會先在“串池”中尋找有沒有“abc”這個(gè)字符串;

      如果有則直接將對象指向串池中對應(yīng)的地址佛析,如果沒有則在串池中創(chuàng)建一個(gè)“abc”字符串。所以:

      String str1 = "abc";
      String str2 = "abc";
      Str1 == str2 //返回值是ture;他們的地址是一樣的彪蓬。
          //也就是說str1和str2都指向了代碼空間中相同的一個(gè)地址寸莫,而這個(gè)地址空間保存就是是字符串"abc"
          //字符串是不可改變的類型,所以可以共享档冬。所以串池里不會有相同的兩個(gè)字符串膘茎。
      
    • 如果用 String str = new String("abc") 則直接開辟一塊內(nèi)存放"abc"這個(gè)字符串桃纯。所以上面這語句,創(chuàng)建兩個(gè)"abc"披坏,一個(gè)在池态坦,一個(gè)是對象

      String str = new String("abc")
      String str2 = new String("abc");
      Str == str2 //返回值是false;他們的地址是不一樣的。
      

//即是說str和str2分別指向了堆空間中不同的兩個(gè)地址棒拂,而這兩個(gè)地址空間保存的都是字符串"abc"
```

7伞梯、final變量在內(nèi)部類中使用

package com.jvm.study;

public class Test {
    public static void main(String[] args)  {     
    }   
    //局部final變量b
    public void test(final int b) {
        int a = 10;//局部變量a
        //匿名內(nèi)部類
        new Thread(() -> {
            System.out.println(a);//JDK1.7及其之前版本 報(bào)錯(cuò)
            System.out.println(b);
            // a = 1; // 不可修改 Variable used in lambda expression should be final or effectively final
            // b = 1; // 不可修改 Cannot assign a value to final variable 'b'
        }).start();
    }
    /**
     * 上段代碼中,在JDK1.7及其之前版本帚屉,如果把變量a和b前面的任一個(gè)final去掉谜诫,這段代碼都編譯不過。
     * 這段代碼會被編譯成兩個(gè)class文件:Test.class和Test1.class攻旦。
     * 默認(rèn)情況下猜绣,編譯器會為匿名內(nèi)部類和局部內(nèi)部類起名為Outter1.class。
     * 原因是為什么呢敬特?這是因?yàn)閠est()方法里面的參數(shù)a和b掰邢,在運(yùn)行時(shí),main線程快要結(jié)束伟阔,但是thread還沒有開始辣之。
     * 因此需要有一種機(jī)制,在使得運(yùn)行thread線程時(shí)候能夠調(diào)用a和b的值皱炉,怎辦呢怀估?java采用了一種復(fù)制的機(jī)制,
     * 也就說如果局部變量的值在編譯期間就可以確定合搅,則直接在匿名內(nèi)部里面創(chuàng)建一個(gè)拷貝多搀。
     * 如果局部變量的值無法在編譯期間確定,則通過構(gòu)造器傳參的方式來對拷貝進(jìn)行初始化賦值灾部。
     */
}

匿名也會被當(dāng)作普通的類處理康铭,只不過編譯器生成它構(gòu)造方法的時(shí)候,除了將外部類的引用傳遞了過來赌髓,還將基本數(shù)據(jù)類型的變量復(fù)制了一份過來从藤,并把引用數(shù)據(jù)類型的變量引用也傳遞了過來。

因此锁蠕,基本數(shù)據(jù)類型的變量不能修改夷野,不然就會跟外部的變量產(chǎn)生不一致,這樣的話變量的傳遞也就變得毫無意義了荣倾。

JDK1.8之前局部內(nèi)部類和匿名內(nèi)部類訪問的局部變量必須由final修飾悯搔,JDK1.8開始,可以不加final修飾符舌仍,由JVM默認(rèn)添加妒貌。這個(gè)功能稱為:Effectively final 功能者娱,屬于Java的一種語法糖,final關(guān)鍵字語法并沒有發(fā)生變化苏揣。

8、總結(jié)

final關(guān)鍵字主要用在三個(gè)地方:變量推姻、方法平匈、類。
一句話概括:

final關(guān)鍵字修飾類,表示類不可被繼承;final關(guān)鍵字修飾方法,表示方法不可被覆蓋;final關(guān)鍵字修飾變量,表示變量一旦被賦值就不可以更改它的值藏古。java中規(guī)定final修飾成員變量必須顯示指定變量的值,并只能賦值一次增炭。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市拧晕,隨后出現(xiàn)的幾起案子隙姿,更是在濱河造成了極大的恐慌,老刑警劉巖厂捞,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件输玷,死亡現(xiàn)場離奇詭異,居然都是意外死亡靡馁,警方通過查閱死者的電腦和手機(jī)欲鹏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來臭墨,“玉大人赔嚎,你說我怎么就攤上這事‰食冢” “怎么了尤误?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長结缚。 經(jīng)常有香客問我损晤,道長,這世上最難降的妖魔是什么红竭? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任沉馆,我火速辦了婚禮,結(jié)果婚禮上德崭,老公的妹妹穿的比我還像新娘斥黑。我一直安慰自己,他們只是感情好眉厨,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布锌奴。 她就那樣靜靜地躺著,像睡著了一般憾股。 火紅的嫁衣襯著肌膚如雪鹿蜀。 梳的紋絲不亂的頭發(fā)上箕慧,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機(jī)與錄音茴恰,去河邊找鬼颠焦。 笑死,一個(gè)胖子當(dāng)著我的面吹牛往枣,可吹牛的內(nèi)容都是我干的伐庭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼分冈,長吁一口氣:“原來是場噩夢啊……” “哼圾另!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起雕沉,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤集乔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后坡椒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扰路,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年倔叼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了幼衰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,030評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡缀雳,死狀恐怖渡嚣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情肥印,我是刑警寧澤识椰,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站深碱,受9級特大地震影響腹鹉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜敷硅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一功咒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧绞蹦,春花似錦力奋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春猿挚,著一層夾襖步出監(jiān)牢的瞬間咐旧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工绩蜻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留铣墨,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓办绝,卻偏偏與公主長得像伊约,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子八秃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容