亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > 綜合 > 正文

Kotlin中局部方法的深入探究

2024-07-21 23:03:50
字體:
來源:轉載
供稿:網友

前言

Kotlin是由開發過IntelliJ IDEA、Android Studio、PyCharm等IDE的著名IDE廠商JetBrains公司設計并開源的編程語言。2011年7月推出的Kotlin項目深受《Effective Java》的影響,直到2016年2月15日第一個官方穩定版本Kotlin v1.0才正式發布,2017年Google I/O開發者大會中,Google宣布Kotlin成為Android開發的一級語言,Kotlin “轉正”。

在Kotlin中,定義方法很有趣,不僅僅因為方法的關鍵字是fun(function前幾個字符),還是因為你會驚奇的發現,它允許我們在方法中定義方法。如下

fun methodA() { fun methodB() { } methodB() //valid}//methodB() invalid

其中

  • methodB定義在methodA的方法體中,即methodB被稱為局部方法或局部函數
  • methodB只能在methodA中方法調用
  • methodB在methodA方法外調用,會引起編譯錯誤

既然Kotlin支持了局部方法,相比它應該有什么特殊的用武之地呢

首先它的特點還是像它的名字一樣,局部,這就意味著它有著無可比擬的更小范圍的限定能力。保證了小范圍的可用性,隔絕了潛在的不相關調用的可能。

作為編程中的金科玉律,方法越小越好,相比縱向冗長的代碼片段,將其按照職責切分成功能單一的小的局部方法,最后組織起來調用,會讓我們的代碼顯得更加的有條理和清晰。

作為一個程序員,好奇應該是他的特質之一,我們應該會想要研究一下,局部方法的實現原理是什么,至少我們在Java時代從來沒有見過這種概念。

其實這件事仔細研究起來,還是有不少細節的。因為這其中局部方法可以捕獲外部的變量也可以不捕獲外部的變量。

下面就是捕獲外部變量的一種情況

fun outMethodCapture(args: Array<String>) { fun checkArgs() { if (args.isEmpty()) {  println("innerMethod check args")  Throwable().printStackTrace() } } checkArgs()}

這其中,局部方法checkArgs捕獲了outMethodCapture的參數args。

所以,不捕獲外部變量的情況也不難理解,如下,即checkArgs處理args都是通過參數傳遞的。

fun outMethodNonCapture(args: Array<String>) { fun checkArgs(args: Array<String>) { if (args.isEmpty()) {  println("outMethodNonCapture check args")  Throwable().printStackTrace() } } checkArgs(args)}

首先我們分析一下捕獲變量的局部方法的實現原理

public static final void outMethodCapture(@NotNull final String[] args) { Intrinsics.checkParameterIsNotNull(args, "args"); <undefinedtype> checkArgs$ = new Function0() { // $FF: synthetic method // $FF: bridge method public Object invoke() { this.invoke(); return Unit.INSTANCE; } public final void invoke() { Object[] var1 = (Object[])args; if(var1.length == 0) {  String var2 = "innerMethod check args";  System.out.println(var2);  (new Throwable()).printStackTrace(); } } }; checkArgs$.invoke();}

如上實現原理,就是局部方法實現其實就是實現了一個匿名內部類的實例,然后再次調用即可。 對于不捕獲的局部方法要稍有不同,首先我們反編譯得到對應的Java代碼

public static final void outMethodNonCapture(@NotNull String[] args) { Intrinsics.checkParameterIsNotNull(args, "args"); <undefinedtype> checkArgs$ = null.INSTANCE; checkArgs$.invoke(args);}

我們得到的是一個不完整的代碼,這時候需要我們前往項目工程,結合一些對應的class文件分析。首先我們找到類似這樣的文件MainKt$outMethodCapture$1.class(其class文件按照”文件名$方法名$內部類序號”的規則)。

使用javap方法再次反編譯分析該文件,注意對于$符號需要簡單處理一下。

? KotlinInnerFunction javap -c "MainKt/$outMethodNonCapture/$1.class"Compiled from "Main.kt"final class MainKt$outMethodNonCapture$1 extends kotlin.jvm.internal.Lambda implements kotlin.jvm.functions.Function1<java.lang.String[], kotlin.Unit> { public static final MainKt$outMethodNonCapture$1 INSTANCE; public java.lang.Object invoke(java.lang.Object); Code:  0: aload_0  1: aload_1  2: checkcast  #11     // class "[Ljava/lang/String;"  5: invokevirtual #14     // Method invoke:([Ljava/lang/String;)V  8: getstatic  #20     // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;  11: areturn public final void invoke(java.lang.String[]); Code:  0: aload_1  1: ldc   #23     // String args  3: invokestatic #29     // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V  6: aload_1  7: checkcast  #31     // class "[Ljava/lang/Object;"  10: astore_2  11: aload_2  12: arraylength  13: ifne   20  16: iconst_1  17: goto   21  20: iconst_0  21: ifeq   44  24: ldc   #33     // String outMethodNonCapture check args  26: astore_2  27: getstatic  #39     // Field java/lang/System.out:Ljava/io/PrintStream;  30: aload_2  31: invokevirtual #45     // Method java/io/PrintStream.println:(Ljava/lang/Object;)V  34: new   #47     // class java/lang/Throwable  37: dup  38: invokespecial #51     // Method java/lang/Throwable."<init>":()V  41: invokevirtual #54     // Method java/lang/Throwable.printStackTrace:()V  44: return MainKt$outMethodNonCapture$1(); Code:  0: aload_0  1: iconst_1  2: invokespecial #61     // Method kotlin/jvm/internal/Lambda."<init>":(I)V  5: return static {}; Code:  0: new   #2     // class MainKt$outMethodNonCapture$1  3: dup  4: invokespecial #80     // Method "<init>":()V  7: putstatic  #82     // Field INSTANCE:LMainKt$outMethodNonCapture$1;  10: return}

上面的類其實比較簡單,更重要的這是一個單例的實現。因為這樣相比捕獲的情況下,減少了匿名內部類的生成和實例的創建,理論上帶來的代價也會更小。

考慮到上面的對比,如果在使用局部方法時,建議使用不捕獲外部變量的方式會更加推薦。

使用注意

是的,使用局部方法有一個注意事項,也就是一種規則約定,那就是需要先定義才能使用,否則會報錯,如下所示

fun outMethodInvalidCase(args: Array<String>) { checkArgs()//invalid unresolved reference fun checkArgs() {  if (args.isEmpty()) {   println("innerMethod check args")   Throwable().printStackTrace()  } } checkArgs()//valid}

但是呢,先定義局部方法,再使用還是有一些問題,這種問題主要表現在代碼可讀性上。

試想一下,如果你進入一個方法,看到的是一連串的局部方法,可能或多或少有點別扭。

但是試想一下,既然有這樣的問題,為什么還要被設計成這個樣子呢。首先,我們先看個小例子

0fun outMethodInvalidCase(args: Array<String>) { checkArgs(args) var a = 0 //the reason why it's unresolved fun checkArgs(args: Array<String>) {  if (args.isEmpty()) {   println("outMethodNonCapture check args")   Throwable().printStackTrace()   a.toString()  } }}

因為局部方法可以capture局部變量,checkArgs捕獲了局部變量a,當第一行代碼checkArgs調用時,而checkArgs看似定義了,但是第二行卻還沒有執行到,導致了編譯問題。

目前,capture變量和非capture的局部方法使用都是一致的,都需要先定義,再使用。

關于Kotlin中的局部方法,我們可以去嘗試來達到限定范圍,拆分方法的目的,在使用時,盡量選擇非捕獲的形式的局部方法。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到kotlin教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩成人中文字幕在线观看| 国外成人在线视频| 久久99久久亚洲国产| 国产69精品99久久久久久宅男| 国产精品黄色影片导航在线观看| 国产97在线|日韩| 91精品国产色综合久久不卡98口| 久久久91精品| 日本精品久久久久久久| 最好看的2019年中文视频| 亚洲综合色av| 亚洲美女福利视频网站| 亚洲最新av在线| 成人激情视频在线播放| 久久久免费高清电视剧观看| 亚洲欧美成人在线| 日本韩国欧美精品大片卡二| 国产91对白在线播放| 久久精品成人欧美大片| 国产精品一区二区三区久久久| 亚洲综合中文字幕在线观看| 国产精品爽黄69天堂a| 亚洲白虎美女被爆操| 欧美日韩精品在线| 国产精品欧美激情在线播放| 亚洲国产欧美一区二区三区久久| 欧美专区中文字幕| 色综合久综合久久综合久鬼88| 国模极品一区二区三区| 成人免费视频在线观看超级碰| 亚洲欧美日韩国产精品| 久久久亚洲成人| 91精品久久久久久久久| 欧美成人午夜激情| 三级精品视频久久久久| 成人免费视频网| 国产精品久久久久久久久免费| 国产精品高潮呻吟久久av无限| 欧美一区二区三区……| 日韩成人中文字幕| 欧美裸体xxxx极品少妇| 欧美一区二粉嫩精品国产一线天| 亚洲欧美一区二区精品久久久| 91网站在线免费观看| 红桃视频成人在线观看| 欧美亚洲另类视频| 欧美日韩亚洲天堂| 日韩av三级在线观看| 亚洲人成网7777777国产| 欧美极品xxxx| 亚洲一区二区中文字幕| 亚洲人成亚洲人成在线观看| 欧美性猛交xxxx免费看久久久| 这里只有精品在线观看| 欧美日韩国产999| 日韩av影视在线| 中文字幕综合在线| 91国内在线视频| 精品国产欧美一区二区五十路| 日韩福利在线播放| 成人av在线网址| 国产精品扒开腿做爽爽爽视频| 亚洲美女又黄又爽在线观看| 欧美成人手机在线| 国产女人精品视频| 国产一区二区日韩| 91成人天堂久久成人| 欧美成人激情在线| 欧美亚洲在线观看| 久久精品国产v日韩v亚洲| 久久九九精品99国产精品| 亚洲精品久久久久中文字幕二区| 萌白酱国产一区二区| 久久中国妇女中文字幕| 日本精品久久久久久久| 欧美一性一乱一交一视频| 国产美女精品免费电影| 成人黄色av免费在线观看| 97精品久久久中文字幕免费| 91久久精品日日躁夜夜躁国产| 国产精品亚洲第一区| 国产精品久久久久秋霞鲁丝| 亚洲国产精品字幕| 国内偷自视频区视频综合| 98视频在线噜噜噜国产| 日韩av在线免费播放| 日韩在线免费视频| 97热精品视频官网| 日本韩国欧美精品大片卡二| 97精品欧美一区二区三区| 国产一区二区丝袜| 欧美国产日韩二区| 亚洲人成免费电影| 欧美激情一区二区久久久| 一个人www欧美| 欧美大胆在线视频| 亚洲一区二区中文字幕| 91免费电影网站| 日韩在线视频一区| 高清欧美一区二区三区| 福利一区视频在线观看| 91精品在线观| 欧美黑人极品猛少妇色xxxxx| 亚洲午夜精品视频| 97高清免费视频| 久久在精品线影院精品国产| 日韩av在线导航| 久久香蕉国产线看观看av| 欧美一级大片在线免费观看| 欧美精品一区二区三区国产精品| 欧美性猛交xxxx富婆弯腰| 欧美丝袜美女中出在线| www.久久久久| 欧美视频专区一二在线观看| 中文字幕欧美日韩| 亚洲免费电影一区| 国产精品久久999| 97精品欧美一区二区三区| 国产精品视频内| 欧美日韩国产专区| 欧美亚洲国产精品| 日本一区二三区好的精华液| 91嫩草在线视频| 欧美福利视频在线观看| 亚洲欧洲美洲在线综合| 欧美成人激情视频| 久久人人爽亚洲精品天堂| 国产精品精品久久久| 2019中文字幕在线| 成人xvideos免费视频| 欧美在线视频导航| 欧美国产日韩一区二区在线观看| 少妇高潮 亚洲精品| 中文字幕日韩av| 亚洲综合第一页| 人人澡人人澡人人看欧美| 91丨九色丨国产在线| 日韩av片永久免费网站| 日韩福利在线播放| 欧美成人剧情片在线观看| 欧美成人精品xxx| 久久中文精品视频| 亚洲精品99999| 中文字幕无线精品亚洲乱码一区| 91精品久久久久久久久久久久久久| 亚洲free性xxxx护士hd| 亚洲免费中文字幕| 高清视频欧美一级| 欧美激情xxxx| 日韩精品视频免费专区在线播放| 国产98色在线| 国产91精品青草社区| 日韩av一区在线观看| 国产精品91久久久| 在线观看91久久久久久| 38少妇精品导航| 中文字幕日韩av电影| 92国产精品久久久久首页| 久久精品一区中文字幕| 91精品在线国产| 91九色视频在线| 久久五月天综合| 日韩电影免费观看在线| 91成人免费观看网站|