終于明白為什么要加 final 關(guān)鍵字了某饰!

在開發(fā)過程中,由于習(xí)慣的原因善绎,我們可能對(duì)某種編程語言的一些特性習(xí)以為常黔漂,特別是只用一種語言作為日常開發(fā)的情況。但是當(dāng)你使用超過一種語言進(jìn)行開發(fā)的時(shí)候就會(huì)發(fā)現(xiàn)禀酱,雖然都是高級(jí)語言炬守,但是它們之間很多特性都是不太相同的。

現(xiàn)象描述

在 Java 8 之前剂跟,匿名內(nèi)部類在使用外部成員的時(shí)候减途,會(huì)報(bào)錯(cuò)并提示 “Cannot refer to a non-final variable arg inside an inner class defined in a different method”

below-java8.jpg

但是在 Java 8 之后,類似場(chǎng)景卻沒有再提示了:

normal-use.jpg

難道是此類變量可以隨便改動(dòng)了嗎曹洽?當(dāng)然不是鳍置,當(dāng)你試圖修改這些變量的時(shí)候,仍然會(huì)提示錯(cuò)誤:

try-to-change.jpg

可以看到衣洁,當(dāng)試圖修改基本數(shù)據(jù)類型的變量時(shí)墓捻,編譯器的警告變成了 “Varible 'num' is accessed from within inner class, need to be final or effectively final”,很遺憾坊夫,仍然不能修改砖第。相比之下,Kotlin 是沒有這個(gè)限制的:

usage-in-kt.jpg

原因分析

從表面上當(dāng)然看不出什么原因环凿,看看編譯器做了什么工作吧梧兼!運(yùn)行 javac 命令后生成了幾個(gè) .class 文件:

generated-files.jpg

不難推斷,這個(gè) TestInnerClass$1.class 就是匿名內(nèi)部類編譯后的文件智听,看看它反編譯后是什么內(nèi)容:

class TestInnerClass$1 extends InnerClass {
    TestInnerClass$1(TestInnerClass var1, int var2, DataBean var3) {
        super(var1);
        this.this$0 = var1;
        this.val$num = var2;
        this.val$bean = var3;
    }

    void doSomething() {
        super.doSomething();
        System.out.println("num = " + this.val$num);
        System.out.println("bean name is: " + this.val$bean.name);
    }
}

原來羽杰,匿名內(nèi)部類也會(huì)被當(dāng)作普通的類處理,只不過編譯器生成它構(gòu)造方法的時(shí)候到推,除了將外部類的引用傳遞了過來考赛,還將基本數(shù)據(jù)類型的變量復(fù)制了一份過來,并把引用數(shù)據(jù)類型的變量引用也傳遞了過來莉测。因此颜骤,基本數(shù)據(jù)類型的變量當(dāng)然不能修改了,不然就會(huì)跟外部的變量產(chǎn)生不一致捣卤,這樣的話變量的傳遞也就變得毫無意義了忍抽。

final 關(guān)鍵字除了能讓類不能被繼承之外八孝,對(duì)應(yīng)到這種場(chǎng)景,就是讓變量也不能被重新賦值鸠项。

情景對(duì)比

但是為什么對(duì)于 Kotlin 來說可以在匿名內(nèi)部類中直接修改基本數(shù)據(jù)類型的值呢干跛?查看 Kotlin 編譯后反編譯回來的內(nèi)容:

   public final void useNestedClass(@NotNull final TestNestedClass.DataBean bean) {
      Intrinsics.checkParameterIsNotNull(bean, "bean");
      final IntRef num = new IntRef();//---1
      num.element = 1;//---2
      String var3 = "before action, num = " + num.element;
      System.out.println(var3);
      <undefinedtype> nestedClass = new TestNestedClass.NestedClass() {
         public void doSomething() {
            num.element = 678;//---3
            bean.setName("xyz");
            String var1 = "num = " + num.element;
            System.out.println(var1);
            var1 = "bean name is: " + bean.getName();
            System.out.println(var1);
         }
      };
      nestedClass.doSomething();
      String var4 = "after action, num = " + num.element;//---4
      System.out.println(var4);
   }

可以發(fā)現(xiàn),當(dāng)需要傳遞基本數(shù)據(jù)類型的變量時(shí)祟绊,Kotlin 編譯器會(huì)將這些數(shù)據(jù)進(jìn)行包裝楼入,從而由值傳遞變?yōu)橐脗鬟f,這樣內(nèi)部的修改當(dāng)然就不會(huì)影響到外部了久免。

驗(yàn)證一下浅辙,當(dāng)變量不進(jìn)行傳遞時(shí),Kotlin 編譯器是怎么處理的:

   public final void useNestedClass(@NotNull TestNestedClass.DataBean bean) {
      Intrinsics.checkParameterIsNotNull(bean, "bean");
      int num = 1;
      String var3 = "before action, num = " + num;
      System.out.println(var3);
      int num = 678;
      var3 = "after action, num = " + num;
      System.out.println(var3);
   }

哈哈阎姥,并沒有多此一舉记舆,點(diǎn)個(gè)贊!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末呼巴,一起剝皮案震驚了整個(gè)濱河市泽腮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌衣赶,老刑警劉巖诊赊,帶你破解...
    沈念sama閱讀 221,331評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異府瞄,居然都是意外死亡碧磅,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,372評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門遵馆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鲸郊,“玉大人,你說我怎么就攤上這事货邓「汛椋” “怎么了?”我有些...
    開封第一講書人閱讀 167,755評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵换况,是天一觀的道長(zhǎng)职辨。 經(jīng)常有香客問我,道長(zhǎng)戈二,這世上最難降的妖魔是什么舒裤? 我笑而不...
    開封第一講書人閱讀 59,528評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮觉吭,結(jié)果婚禮上腾供,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好台腥,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,526評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著绒北,像睡著了一般黎侈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上闷游,一...
    開封第一講書人閱讀 52,166評(píng)論 1 308
  • 那天峻汉,我揣著相機(jī)與錄音,去河邊找鬼脐往。 笑死休吠,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的业簿。 我是一名探鬼主播瘤礁,決...
    沈念sama閱讀 40,768評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼梅尤!你這毒婦竟也來了柜思?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,664評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤巷燥,失蹤者是張志新(化名)和其女友劉穎赡盘,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缰揪,經(jīng)...
    沈念sama閱讀 46,205評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡陨享,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,290評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了钝腺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抛姑。...
    茶點(diǎn)故事閱讀 40,435評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拍屑,靈堂內(nèi)的尸體忽然破棺而出途戒,到底是詐尸還是另有隱情,我是刑警寧澤僵驰,帶...
    沈念sama閱讀 36,126評(píng)論 5 349
  • 正文 年R本政府宣布喷斋,位于F島的核電站,受9級(jí)特大地震影響蒜茴,放射性物質(zhì)發(fā)生泄漏星爪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,804評(píng)論 3 333
  • 文/蒙蒙 一粉私、第九天 我趴在偏房一處隱蔽的房頂上張望顽腾。 院中可真熱鬧,春花似錦、人聲如沸抄肖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,276評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)漓摩。三九已至裙士,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間管毙,已是汗流浹背腿椎。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留夭咬,地道東北人啃炸。 一個(gè)月前我還...
    沈念sama閱讀 48,818評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像卓舵,于是被迫代替她去往敵國(guó)和親南用。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,442評(píng)論 2 359