日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
研究學(xué)習(xí)Kotlin的一些方法

Kotlin是一門(mén)讓人感到很舒服的語(yǔ)言,相比Java來(lái)說(shuō),它更加簡(jiǎn)潔,省去了瑣瑣碎碎的語(yǔ)法工作,同時(shí)了提供了類(lèi)似Lambda,String template,Null Safe Operator等特性。讓開(kāi)發(fā)者用起來(lái)得心應(yīng)手。

成都創(chuàng)新互聯(lián)服務(wù)項(xiàng)目包括富順網(wǎng)站建設(shè)、富順網(wǎng)站制作、富順網(wǎng)頁(yè)制作以及富順網(wǎng)絡(luò)營(yíng)銷(xiāo)策劃等。多年來(lái),我們專(zhuān)注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,富順網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到富順省份的部分城市,未來(lái)相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

普通的Java/Android程序員通常只需要很短的時(shí)間就能快速使用Kotlin。綜合Kotlin的諸多優(yōu)點(diǎn),加上Flipboard美國(guó)團(tuán)隊(duì)自2015年已引入Kotlin,F(xiàn)lipboard中國(guó)團(tuán)隊(duì)也已經(jīng)開(kāi)始采用Kotlin來(lái)作為Android主要開(kāi)發(fā)語(yǔ)言。

雖然Kotlin使用簡(jiǎn)單快捷,然而由于自己的深入研究的習(xí)慣導(dǎo)致每接觸到Kotlin的新功能,就馬不停蹄的研究它的本質(zhì),這里總結(jié)一下關(guān)于如何研究Kotlin的一些方法來(lái)快速研究掌握Kotlin。

到底研究什么

比如Kotlin中提供了一種類(lèi)型叫做Object,使用它我們可以快速實(shí)現(xiàn)單例模式的應(yīng)用。代碼特別的簡(jiǎn)單

 
 
 
 
  1. object AppSettings { 
  2. }

那么問(wèn)題來(lái)了,kotlin這個(gè)object類(lèi)型的類(lèi)是如何實(shí)現(xiàn)的呢,Null安全操作符的實(shí)現(xiàn)原理,Lambda表達(dá)式是基于內(nèi)部類(lèi)還是真正的Lambda,這些問(wèn)題就是我們要研究的對(duì)象。

怎么研究

  • Kotlin和Java都是運(yùn)行在JVM上,但是實(shí)際上JVM并不認(rèn)識(shí)Java和Kotlin,因?yàn)樗缓蚥ytecode(即class文件)打交道。
  • 因而通過(guò)研究bytecode,我們是可以了解Kotlin的一些深入原理的
  • 由于同一份bytecode反編譯成java和kotlin文件是等價(jià)的,所以將kotlin編譯后的class文件反編譯成Java,也是具有參考和研究?jī)r(jià)值的。

實(shí)踐方法有哪些

  • 利用Kotlin插件
  • 利用kotlinc,javap等工具

一些實(shí)踐

Null Safe Operator實(shí)現(xiàn)原理

在Java中,我們經(jīng)常會(huì)遇到空指針的問(wèn)題,Kotlin特意增加了一個(gè)空指針安全操作符?。使用起來(lái)如下

 
 
 
 
  1. fun testNullSafeOperator(string: String?) {
  2.     System.out.println(string?.toCharArray()?.getOrNull(10)?.hashCode())
  3. }

當(dāng)我們進(jìn)行這樣的調(diào)用時(shí)

 
 
 
 
  1. testNullSafeOperator(null)
  2. testNullSafeOperator("12345678901")
  3. testNullSafeOperator("123")

得到的輸出結(jié)果為

 
 
 
 
  1. null
  2. 49
  3. null

從結(jié)果可見(jiàn),并沒(méi)有像Java那樣拋出NullPointerException,而是遇到空指針則不繼續(xù)執(zhí)行了。

那么Kotlin的這個(gè)空指針安全操作符是如何工作的呢,我們可以借助IntelliJ IDE的Kotlin插件來(lái)輔助我們研究,步驟如下

  • 使用IntelliJ IDE打開(kāi)一個(gè)待研究的Kotlin文件(需確保Kotlin插件已安裝)
  • 按照下圖依次點(diǎn)擊至Show Kotlin Bytecode

  • 上面的步驟操作后,會(huì)得到這樣的bytecode
 
 
 
 
  1. // access flags 0x19
  2.   public final static testNullSafeOperator(Ljava/lang/String;)V
  3.     @Lorg/jetbrains/annotations/Nullable;() // invisible, parameter 0
  4.    L0
  5.     LINENUMBER 11 L0
  6.     GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
  7.     ALOAD 0
  8.     DUP
  9.     IFNULL L1   //對(duì)string字符串判空
  10.     INVOKESTATIC kotlin/text/StringsKt.toCharArray (Ljava/lang/String;)[C
  11.     DUP
  12.     IFNULL L1  //對(duì)CharArray判空
  13.     BIPUSH 10
  14.     INVOKESTATIC kotlin/collections/ArraysKt.getOrNull ([CI)Ljava/lang/Character;
  15.     DUP
  16.     IFNULL L1  //對(duì)Char判空
  17.     INVOKEVIRTUAL java/lang/Object.hashCode ()I
  18.     INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
  19.     GOTO L2
  20.    L1
  21.     POP
  22.     ACONST_NULL
  23.    L2
  24.     INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
  25.    L3
  26.     LINENUMBER 12 L3
  27.     RETURN
  28.    L4
  29.     LOCALVARIABLE string Ljava/lang/String; L0 L4 0
  30.     MAXSTACK = 3
  31.     MAXLOCALS = 1
  32. }

由字節(jié)碼分析可見(jiàn),其實(shí)所謂的 空指針安全操作符其實(shí)內(nèi)部就是以此判空來(lái)確保不出現(xiàn)空指針 ,如果字節(jié)碼不好理解,那我們使用上面的Decompile功能,將bytecode轉(zhuǎn)成Java,如圖操作

反編譯后得到的Java代碼為

 
 
 
 
  1. public static final void testNullSafeOperator(@Nullable String string) {
  2.       PrintStream var10000;
  3.       Integer var5;
  4.       label18: {
  5.          var10000 = System.out;
  6.          if(string != null) {
  7.             PrintStream var2 = var10000;
  8.             if(string == null) {
  9.                throw new TypeCastException("null cannot be cast to non-null type java.lang.String");
  10.             }
  11.             char[] var4 = ((String)string).toCharArray();
  12.             Intrinsics.checkExpressionValueIsNotNull(var4, "(this as java.lang.String).toCharArray()");
  13.             char[] var3 = var4;
  14.             var10000 = var2;
  15.             if(var3 != null) {
  16.                Character var10001 = ArraysKt.getOrNull(var3, 10);
  17.                if(var10001 != null) {
  18.                   var5 = Integer.valueOf(var10001.hashCode());
  19.                   break label18;
  20.                }
  21.             }
  22.          }
  23.          var5 = null;
  24.       }
  25.       var10000.println(var5);
  26.    }

這樣讀起來(lái)是不是更加容易理解呢。

Object類(lèi)型研究

這里我們回到Object類(lèi)型,還是再舉個(gè)例子看看如何使用

 
 
 
 
  1. //這是定義
  2. object AppSettings {
  3.     fun updateConfig() {
  4.         //do some updating work
  5.     }
  6. }

關(guān)于應(yīng)用也很簡(jiǎn)單

 
 
 
 
  1. //在Kotlin文件中調(diào)用
  2. AppSettings.updateConfig()
  3. //在Java文件中調(diào)用
  4. AppSettings.INSTANCE.updateConfig();

我們先看一下AppSettings的字節(jié)碼文件

 
 
 
 
  1. // ================AppSettings.class =================
  2. // class version 50.0 (50)
  3. // access flags 0x31
  4. public final class AppSettings {
  5.   // access flags 0x11
  6.   public final updateConfig()V
  7.    L0
  8.     LINENUMBER 7 L0
  9.     RETURN
  10.    L1
  11.     LOCALVARIABLE this LAppSettings; L0 L1 0
  12.     MAXSTACK = 0
  13.     MAXLOCALS = 1
  14.   // access flags 0x2
  15.   private ()V
  16.    L0
  17.     LINENUMBER 4 L0
  18.     ALOAD 0
  19.     INVOKESPECIAL java/lang/Object. ()V
  20.     ALOAD 0
  21.     CHECKCAST AppSettings
  22.     PUTSTATIC AppSettings.INSTANCE : LAppSettings;
  23.     RETURN
  24.    L1
  25.     LOCALVARIABLE this LAppSettings; L0 L1 0
  26.     MAXSTACK = 1
  27.     MAXLOCALS = 1
  28.   // access flags 0x19
  29.   public final static LAppSettings; INSTANCE
  30.   // access flags 0x8
  31.   static ()V
  32.    L0
  33.     LINENUMBER 4 L0
  34.     //靜態(tài)代碼塊中實(shí)例化,即類(lèi)加載時(shí)便開(kāi)始實(shí)例化
  35.     NEW AppSettings
  36.     INVOKESPECIAL AppSettings. ()V
  37.     RETURN
  38.     MAXSTACK = 1
  39.     MAXLOCALS = 0
  40.   @Lkotlin/Metadata;(mv={1, 1, 5}, bv={1, 0, 1}, k=1, d1={"\u0000\u0012\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\u0008\u0002\n\u0002\u0010\u0002\n\u0000\u0008\u00c6\u0002\u0018\u00002\u00020\u0001B\u0007\u0008\u0002\u00a2\u0006\u0002\u0010\u0002J\u0006\u0010\u0003\u001a\u00020\u0004\u00a8\u0006\u0005"}, d2={"LAppSettings;", "", "()V", "updateConfig", "", "production sources for module KotlinObject"})
  41.   // compiled from: AppSettings.kt
  42. }

由此可見(jiàn),Kotlin的object也就是Java的單例模式的實(shí)現(xiàn),在靜態(tài)代碼塊初始化實(shí)例。如果字節(jié)碼沒(méi)有看懂的話,可以嘗試反編譯成Java代碼來(lái)詳細(xì)研究。

Lambda表達(dá)式研究

除此之外,Kotlin也是支持了Lambda表達(dá)式的。由于并非所有的JVM版本都支持invokedynamic(Lambda表達(dá)式依賴的字節(jié)碼指令),比如Java 6的JVM,這其中就包含了許多安卓設(shè)備。所以我們懷疑Kotlin可能是像Scala那樣將lambda表達(dá)式轉(zhuǎn)換成了匿名內(nèi)部類(lèi)。

一個(gè)簡(jiǎn)單的Lambda表達(dá)式例子

 
 
 
 
  1. class Test {
  2.     fun testObservable() {
  3.         val observable = Observable()
  4.         observable.addObserver { o, arg ->
  5.             System.out.println("$o $arg")
  6.         }
  7.     }
  8. }

我們使用插件同樣查看bytecode

 
 
 
 
  1. // ================Test.class =================
  2. // class version 50.0 (50)
  3. // access flags 0x31
  4. public final class Test {
  5.   // access flags 0x11
  6.   public final testObservable()V
  7.    L0
  8.     LINENUMBER 8 L0
  9.     NEW java/util/Observable
  10.     DUP
  11.     INVOKESPECIAL java/util/Observable. ()V
  12.     ASTORE 1
  13.    L1
  14.     LINENUMBER 9 L1
  15.     ALOAD 1
  16.     GETSTATIC Test$testObservable$1.INSTANCE : LTest$testObservable$1;  //這里就是使用了匿名內(nèi)部類(lèi)(常常包含$字符)
  17.     CHECKCAST java/util/Observer
  18.     INVOKEVIRTUAL java/util/Observable.addObserver (Ljava/util/Observer;)V
  19.    L2
  20.     LINENUMBER 12 L2
  21.     RETURN
  22.    L3
  23.     LOCALVARIABLE observable Ljava/util/Observable; L1 L3 1
  24.     LOCALVARIABLE this LTest; L0 L3 0
  25.     MAXSTACK = 2
  26.     MAXLOCALS = 2
  27.   // access flags 0x1
  28.   public ()V
  29.    L0
  30.     LINENUMBER 6 L0
  31.     ALOAD 0
  32.     INVOKESPECIAL java/lang/Object. ()V
  33.     RETURN
  34.    L1
  35.     LOCALVARIABLE this LTest; L0 L1 0
  36.     MAXSTACK = 1
  37.     MAXLOCALS = 1
  38.   @Lkotlin/Metadata;(mv={1, 1, 5}, bv={1, 0, 1}, k=1, d1={"\u0000\u0012\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\u0008\u0002\n\u0002\u0010\u0002\n\u0000\u0018\u00002\u00020\u0001B\u0005\u00a2\u0006\u0002\u0010\u0002J\u0006\u0010\u0003\u001a\u00020\u0004\u00a8\u0006\u0005"}, d2={"LTest;", "", "()V", "testObservable", "", "production sources for module KotlinObject"})
  39.   // access flags 0x18
  40.   final static INNERCLASS Test$testObservable$1 null null
  41.   // compiled from: Space.kt
  42. }
  43. // ================Test$testObservable$1.class =================
  44. // class version 50.0 (50)
  45. // access flags 0x30
  46. //生成的匿名內(nèi)部類(lèi),規(guī)則為  當(dāng)前的類(lèi)名$當(dāng)前的方法名$匿名內(nèi)部類(lèi)序號(hào)
  47. final class Test$testObservable$1 implements java/util/Observer  {
  48.   // access flags 0x11
  49.   public final update(Ljava/util/Observable;Ljava/lang/Object;)V
  50.    L0
  51.     LINENUMBER 10 L0
  52.     GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
  53.     NEW java/lang/StringBuilder
  54.     DUP
  55.     INVOKESPECIAL java/lang/StringBuilder. ()V
  56.     ALOAD 1
  57.     INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/Object;)Ljava/lang/StringBuilder;
  58.     LDC " "
  59.     INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
  60.     ALOAD 2
  61.     INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/Object;)Ljava/lang/StringBuilder;
  62.     INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
  63.     INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
  64.    L1
  65.     LINENUMBER 11 L1
  66.     RETURN
  67.    L2
  68.     LOCALVARIABLE this LTest$testObservable$1; L0 L2 0
  69.     LOCALVARIABLE o Ljava/util/Observable; L0 L2 1
  70.     LOCALVARIABLE arg Ljava/lang/Object; L0 L2 2
  71.     MAXSTACK = 3
  72.     MAXLOCALS = 3 
  73.   // access flags 0x0
  74.   ()V
  75.     ALOAD 0
  76.     INVOKESPECIAL java/lang/Object. ()V
  77.     RETURN
  78.     MAXSTACK = 1
  79.     MAXLOCALS = 1 
  80.   // access flags 0x19
  81.   public final static LTest$testObservable$1; INSTANCE
  82.   // access flags 0x8
  83.   static ()V
  84.     NEW Test$testObservable$1
  85.     DUP
  86.     INVOKESPECIAL Test$testObservable$1. ()V
  87.     PUTSTATIC Test$testObservable$1.INSTANCE : LTest$testObservable$1;
  88.     RETURN
  89.     MAXSTACK = 2
  90.     MAXLOCALS = 0 
  91.   @Lkotlin/Metadata;(mv={1, 1, 5}, bv={1, 0, 1}, k=3, d1={"\u0000\u0016\n\u0000\n\u0002\u0010\u0002\n\u0000\n\u0002\u0018\u0002\n\u0002\u0008\u0002\n\u0002\u0010\u0000\n\u0000\u0010\u0000\u001a\u00020\u00012\u000e\u0010\u0002\u001a\n \u0004*\u0004\u0018\u00010\u00030\u00032\u000e\u0010\u0005\u001a\n \u0004*\u0004\u0018\u00010\u00060\u0006H\n\u00a2\u0006\u0002\u0008\u0007"}, d2={"", "", "o", "Ljava/util/Observable;", "kotlin.jvm.PlatformType", "arg", "", "update"})
  92.   OUTERCLASS Test testObservable ()V
  93.   // access flags 0x18
  94.   final static INNERCLASS Test$testObservable$1 null null
  95.   // compiled from: Space.kt
  96. }

分析字節(jié)碼可以看到有兩個(gè)class文件,因此可以推斷出Kotlin的Lambda表達(dá)式目前是一種基于內(nèi)部類(lèi)的語(yǔ)法糖實(shí)現(xiàn)。

除此之外,我們還可以使用kotlinc(Kotlin編譯器來(lái)驗(yàn)證)

 
 
 
 
  1. kotlinc Test.kt

執(zhí)行完成后,查看生成的class文件

 
 
 
 
  1. ls | grep ^Test
  2. Test$testObservable$1.class
  3. Test.class
  4. Test.kt

當(dāng)然,我們還可以使用javap同樣實(shí)現(xiàn)查看bytecode的功能,即 javap -c className 。

除此之外,我們還可以利用上面的方法研究如下Kotlin的特性

  • lazy初始化
  • when表達(dá)式
  • 方法引用

關(guān)于Kotlin的研究方法目前就是這些,Kotlin很簡(jiǎn)單,但也要知其所以然,方能游刃有余編碼。希望大家可以嘗試Kotlin,并玩的開(kāi)心。


網(wǎng)站名稱(chēng):研究學(xué)習(xí)Kotlin的一些方法
當(dāng)前鏈接:http://www.5511xx.com/article/cocsgcs.html