淺談Kotlin語法篇之頂層函數、中綴調用、解構聲明(四)

簡述: 今天帶來的是Kotlin淺談系列的第四彈,此次主要聊下Kotlin獨有的新特性,Java不具有的。Kotlin是一種增長許多新功能的語言,容許編寫更簡潔易讀的代碼,這使得咱們的代碼更易於維護。例如使用頂層函數和屬性今後消除Java中的static、中綴表達式調用和解構聲明等。java

  • 一、爲何要用頂層函數替代Java中的static函數
  • 二、頂層函數和屬性的基本使用
  • 三、頂層函數實質原理
  • 四、頂層函數使用應注意哪些問題
  • 五、一塊兒嚐嚐中綴調用語法糖
  • 六、中綴調用的基本使用
  • 七、中綴調用實質原理
  • 八、中綴調用應注意哪些問題
  • 九、Kotlin中的解構聲明

1、爲何要用頂層函數替代Java中的static函數

概念: 咱們知道在Java中有靜態函數和靜態屬性概念,它們通常做用就是爲了提供一個全局共享訪問區域和方法。咱們通常的習慣的寫法就是寫一個類包裹一些static修飾的方法,而後在外部訪問的直接利用類名.方法名訪問。apache

問題: 咱們都知道靜態函數內部是不包含狀態的,也就是所謂的純函數,它的輸入僅僅來自於它的參數列表,而它的輸出也僅僅依賴於它參數列表。咱們設想一下這樣開發情景,有時候咱們並不想利用實例對象來調用函數,因此咱們通常會往靜態函數容器類中添加靜態函數,如此反覆,這樣無疑是讓這個類容器膨脹。bash

解決: 在Kotlin中則認爲一個函數或方法有時候並非屬於任何一個類,它能夠獨立存在。因此在Kotlin中相似靜態函數和靜態屬性會去掉外層類的容器,一個函數或者屬性能夠直接定義在一個Kotlin文件的頂層中,在使用的地方只須要import這個函數或屬性便可。若是你的代碼還存在不少以"Util"後綴結尾的工具類,是時候去掉了。jvm

2、頂層函數和屬性的基本使用

在Koltin中根本不須要去定義一些沒有意義包裹靜態函數的容器類,它們都被頂層文件給替代。咱們只須要定義一個Kotlin File,在裏面定義好一些函數(注意: 不須要static關鍵字)。那麼這些函數就能夠當作靜態函數來使用函數

建立一個頂層文件:工具

在頂層文件中定義一個函數:源碼分析

package com.mikyou.kotlin.top

import java.math.BigDecimal

/** * Created by mikyou on 2018/4/10. */
//這個頂層函數不屬於任何一個類,不須要類容器,不須要static關鍵字
fun formateFileSize(size: Double): String {
    if (size < 0) {
        return "0 KB"
    }

    val kBSize = size / 1024
    if (kBSize < 1) {
        return "$size B"
    }

    val mBSize = kBSize / 1024
    if (mBSize < 1) {
        return "${BigDecimal(kBSize.toString()).setScale(1, BigDecimal.ROUND_HALF_UP).toPlainString()} KB"
    }

    val mGSize = mBSize / 1024
    if (mGSize < 1) {
        return "${BigDecimal(mBSize.toString()).setScale(1, BigDecimal.ROUND_HALF_UP).toPlainString()} MB"
    }

    val mTSize = mGSize / 1024
    if (mTSize < 1) {
        return "${BigDecimal(mGSize.toString()).setScale(1, BigDecimal.ROUND_HALF_UP).toPlainString()} GB"
    }
    return "${BigDecimal(mTSize.toString()).setScale(1, BigDecimal.ROUND_HALF_UP).toPlainString()} TB"
}

//測試頂層函數,實際上Kotlin中main函數和Java不同,它能夠不存在任何類容器中,能夠直接定義在一個Kotlin 文件中
//另外一方面也解釋了Kotlin中的main函數不須要了static關鍵字,實際上它本身就是個頂層函數。
fun main(args: Array<String>) {
    println("文件大小: ${formateFileSize(15582.0)}")
}
複製代碼

從以上代碼能夠看出定義一個頂層函數是否是很簡單,那麼問題來了這個formateFileSize函數定義在一個文件內部,在JVM中是怎麼執行的呢?請接着往下看...測試

3、頂層函數實質原理

經過以上例子咱們思考一下頂層函數在JVM中是怎麼運行的,若是你僅僅是在Kotlin中使用這些頂層函數,那麼能夠不用細究。可是若是你是Java和Kotlin混合開發模式,那麼你就有必要深刻內部原理。咱們都知道Kotlin和Java互操做性是很強的,因此就衍生出了一個問題:在Kotlin中定義的頂層函數,在Java能夠調用嗎?答案確定是能夠的。怎麼調用的,請接着看。ui

要想知道內部調用原理很簡單,咱們只須要把上面例子代碼反編譯成Java代碼就一目瞭然了。這裏科普一下反編譯Kotlin代碼步驟,由於這是查看Kotlin語法糖背後實質很好的方法。this

步驟一: 確認IDE安裝好了Kotlin Plugin

步驟二: 在IDE中打開你須要查看反編譯的代碼文件,而後打開頂部的"Tools",選擇"Kotlin",再選擇"Show Kotlin ByteCode"

步驟三: 左邊是Kotlin的源碼,右邊是Kotlin的ByteCode

步驟四: 點擊右側「Decompile」

package com.mikyou.kotlin.top;

import java.math.BigDecimal;
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;

@Metadata(
   mv = {1, 1, 9},
   bv = {1, 0, 2},
   k = 2,
   d1 = {"\u0000\u001c\n\u0000\n\u0002\u0010\u000e\n\u0000\n\u0002\u0010\u0006\n\u0000\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\u0011\n\u0002\b\u0002\u001a\u000e\u0010\u0000\u001a\u00020\u00012\u0006\u0010\u0002\u001a\u00020\u0003\u001a\u0019\u0010\u0004\u001a\u00020\u00052\f\u0010\u0006\u001a\b\u0012\u0004\u0012\u00020\u00010\u0007¢\u0006\u0002\u0010\b¨\u0006\t"},
   d2 = {"formateFileSize", "", "size", "", "main", "", "args", "", "([Ljava/lang/String;)V", "production sources for module Function"}
)
public final class TopExtFileFormatKt {//通常以文件名+"Kt"後綴做爲容器類名
   @NotNull
   public static final String formateFileSize(double size) {//頂層函數反編譯成Java中靜態函數
      if(size < (double)0) {
         return "0 KB";
      } else {
         double kBSize = size / (double)1024;
         if(kBSize < (double)1) {
            return "" + size + " B";
         } else {
            double mBSize = kBSize / (double)1024;
            if(mBSize < (double)1) {
               return "" + (new BigDecimal(String.valueOf(kBSize))).setScale(1, 4).toPlainString() + " KB";
            } else {
               double mGSize = mBSize / (double)1024;
               if(mGSize < (double)1) {
                  return "" + (new BigDecimal(String.valueOf(mBSize))).setScale(1, 4).toPlainString() + " MB";
               } else {
                  double mTSize = mGSize / (double)1024;
                  return mTSize < (double)1?"" + (new BigDecimal(String.valueOf(mGSize))).setScale(1, 4).toPlainString() + " GB":"" + (new BigDecimal(String.valueOf(mTSize))).setScale(1, 4).toPlainString() + " TB";
               }
            }
         }
      }
   }

   public static final void main(@NotNull String[] args) {//頂層函數反編譯成Java中靜態函數
      Intrinsics.checkParameterIsNotNull(args, "args");
      String var1 = "文件大小: " + formateFileSize(15582.0D);
      System.out.println(var1);
   }
}

複製代碼

經過以上的代碼能夠總結出兩點內容:

  • 一、頂層文件會反編譯成一個容器類。(類名通常默認就是頂層文件名+"Kt"後綴,注意容器類名能夠自定義)
  • 二、頂層函數會反編譯成一個static靜態函數,如代碼中的formateFileSize和main函數

想必到這裏你大概猜到了Java中如何調用Kotlin中的頂層函數了吧。調用方式很簡單,就是利用反編譯生成的類做爲靜態函數容器類直接調用對應的函數

package com.mikyou.kotlin.top;

/**
 * Created by mikyou on 2018/4/10.
 */
public class TopExtTest {
    public static void main(String[] args) {
        System.out.println("文件大小: " + TopExtFileFormatKt.formateFileSize(1343553));// Java中調用Kotlin中定義頂層函數,通常是頂層文件名+"Kt"後綴做爲靜態函數的類名調用相應函數
    }
}

複製代碼

4、頂層函數使用應注意的問題

Kotlin中的頂層函數反編譯成的Java中的容器類名通常是頂層文件名+「Kt」後綴做爲類名,可是也是能夠自定義的。也就是說頂層文件名和生成容器類名沒有必然的聯繫。經過Kotlin中的@file: JvmName("自定義生成類名")註解就能夠自動生成對應Java調用類名,注意須要放在文件頂部,在package聲明的前面

//經過@file: JvmName("FileFormatUtil")註解,將生成的類名修改成FileFormatUtil,而且調用的時候直接調用FileFormatUtil.formateFileSize()便可
//放在文件頂部,在package聲明的前面
@file: JvmName("FileFormatUtil")

package com.mikyou.kotlin.top

import java.math.BigDecimal

/** * Created by mikyou on 2018/4/10. */
//這個頂層函數不屬於任何一個類,不須要類容器,不須要static關鍵字
fun formateFileSize(size: Double): String {
    if (size < 0) {
        return "0 KB"
    }

    val kBSize = size / 1024
    if (kBSize < 1) {
        return "$size B"
    }

    val mBSize = kBSize / 1024
    if (mBSize < 1) {
        return "${BigDecimal(kBSize.toString()).setScale(1, BigDecimal.ROUND_HALF_UP).toPlainString()} KB"
    }

    val mGSize = mBSize / 1024
    if (mGSize < 1) {
        return "${BigDecimal(mBSize.toString()).setScale(1, BigDecimal.ROUND_HALF_UP).toPlainString()} MB"
    }

    val mTSize = mGSize / 1024
    if (mTSize < 1) {
        return "${BigDecimal(mGSize.toString()).setScale(1, BigDecimal.ROUND_HALF_UP).toPlainString()} GB"
    }
    return "${BigDecimal(mTSize.toString()).setScale(1, BigDecimal.ROUND_HALF_UP).toPlainString()} TB"
}

//測試頂層函數,實際上Kotlin中main函數和Java不同,它能夠不存在任何類容器中,能夠直接定義在一個Kotlin 文件中
//另外一方面也解釋了Kotlin中的main函數不須要了static關鍵字,實際上它本身就是個頂層函數。
fun main(args: Array<String>) {
    println("文件大小: ${formateFileSize(15582.0)}")
}
複製代碼

而後咱們再來一塊兒看看反編譯成Java代碼變成什麼樣了

package com.mikyou.kotlin.top;

import java.math.BigDecimal;
import kotlin.Metadata;
import kotlin.jvm.JvmName;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;

@Metadata(
   mv = {1, 1, 9},
   bv = {1, 0, 2},
   k = 2,
   d1 = {"\u0000\u001c\n\u0000\n\u0002\u0010\u000e\n\u0000\n\u0002\u0010\u0006\n\u0000\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\u0011\n\u0002\b\u0002\u001a\u000e\u0010\u0000\u001a\u00020\u00012\u0006\u0010\u0002\u001a\u00020\u0003\u001a\u0019\u0010\u0004\u001a\u00020\u00052\f\u0010\u0006\u001a\b\u0012\u0004\u0012\u00020\u00010\u0007¢\u0006\u0002\u0010\b¨\u0006\t"},
   d2 = {"formateFileSize", "", "size", "", "main", "", "args", "", "([Ljava/lang/String;)V", "production sources for module Function"}
)
@JvmName(//注意這裏多了註解
   name = "FileFormatUtil"
)
public final class FileFormatUtil {//這裏生成的類名就是註解中自定義生成的類名了
   @NotNull
   public static final String formateFileSize(double size) {
      if(size < (double)0) {
         return "0 KB";
      } else {
         double kBSize = size / (double)1024;
         if(kBSize < (double)1) {
            return "" + size + " B";
         } else {
            double mBSize = kBSize / (double)1024;
            if(mBSize < (double)1) {
               return "" + (new BigDecimal(String.valueOf(kBSize))).setScale(1, 4).toPlainString() + " KB";
            } else {
               double mGSize = mBSize / (double)1024;
               if(mGSize < (double)1) {
                  return "" + (new BigDecimal(String.valueOf(mBSize))).setScale(1, 4).toPlainString() + " MB";
               } else {
                  double mTSize = mGSize / (double)1024;
                  return mTSize < (double)1?"" + (new BigDecimal(String.valueOf(mGSize))).setScale(1, 4).toPlainString() + " GB":"" + (new BigDecimal(String.valueOf(mTSize))).setScale(1, 4).toPlainString() + " TB";
               }
            }
         }
      }
   }

   public static final void main(@NotNull String[] args) {
      Intrinsics.checkParameterIsNotNull(args, "args");
      String var1 = "文件大小: " + formateFileSize(15582.0D);
      System.out.println(var1);
   }
}

複製代碼

這樣Java調用自定義類名頂層函數就更加天然,通常建議使用註解修改類名,這樣在Java層調用仍是咱們習慣工具類的命名,徹底沒法感知這個函數是來自Java中仍是Kotlin中定義的,作到徹底透明。

package com.mikyou.kotlin.top;

/** * Created by mikyou on 2018/4/10. */
public class TopExtTest {
    public static void main(String[] args) {
        System.out.println("文件大小: " + FileFormatUtil.formateFileSize(1343553));// Java中調用Kotlin中定義頂層函數,若是自定義生成類名,直接用定義類名調用。
    }
}

複製代碼

5、一塊兒嚐嚐中綴調用語法糖

中綴調用看起來是很高級概念,實際上原理很簡單,可是它在語法層面簡化了不少,更方便以及更容易理解,讓咱們寫代碼會更加接近天然語言。我我的理解中綴調用實際上就是把原來只有一個參數的函數調用簡化成兩個操做直接使用相似中綴運算符調用,省略了類名或者對象名+"."+函數名調用方式。廢話很少說,直接發波糖

  • 例子一 初始化map
package com.mikyou.kotlin.infix

/** * Created by mikyou on 2018/4/10. */
//普通利用Pair()初始化一個map
fun main(args: Array<String>) {
    val map = mapOf(Pair(1, "A"), Pair(2, "B"), Pair(3, "C"))
    map.forEach { key, value ->
        println("key: $key value:$value")
    }
}

//利用to函數初始化一個map
fun main(args: Array<String>) {
    val map = mapOf(1.to("A"), 2.to("B"), 3.to("C"))
    map.forEach { key, value ->
        println("key: $key value:$value")
    }
}

//利用to函數中綴調用初始化一個map
fun main(args: Array<String>) {
    val map = mapOf(1 to "A", 2 to "B", 3 to "C")//to實際上一個返回Pair對象的函數,不是屬於map結構內部的運算符,可是to在語法層面使用很像中綴運算符調用
    map.forEach { key, value ->
        println("key: $key value:$value")
    }
}
複製代碼
  • 例子二 字符串比較
//普通使用字符串對比調用StringUtils.equals(strA, strB)
fun main(args: Array<String>) {
	val strA = "A"
	val strB = "B"
	if (StringUtils.equals(strA, strB)) {//這裏對比字符串是了apache中的StringUtils
		println("str is the same")
	} else {
		println("str is the different")
	}
}

//利用中綴調用sameAs對比兩個字符串
fun main(args: Array<String>) {
	val strA = "A"
	val strB = "B"
	if (strA sameAs strB) {//中綴調用 sameAs
		println("str is the same")
	} else {
		println("str is the different")
	}
}
複製代碼
  • 例子三 判斷一個元素是否在集合中
//普通調用集合contains方法判斷元素是否在集合中
fun main(args: Array<String>) {
    val list = listOf(1, 3, 5, 7, 9)
    val element = 2
    if (list.contains(element)) {
        println("element: $element is into list")
    } else {
        println("element: $element is not into list")
    }
}

//利用中綴調用into判斷元素是否在集合中
fun main(args: Array<String>) {
    val list = listOf(1, 3, 5, 7, 9)
    val element = 2
    if (element into list) {//中綴調用,這樣的寫法,會更加接近咱們天然語言的表達,更容易理解
        println("element: $element is into list")
    } else {
        println("element: $element is not into list")
    }
}
複製代碼

6、中綴調用的基本使用

中綴調用使用很是簡單,準確來講它使用相似加減乘除運算操做符的使用。調用結構: A (中綴函數名) B 例如: element into list

7、中綴調用實質原理

7.1 to函數系統內置中綴調用

  • 源碼分析
public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
複製代碼

分析: 使用infix關鍵字修飾的函數,傳入A,B兩個泛型對象,「A.to(B)」結構,是一種特殊結構暫時把它叫作帶接收者的結構,以致於後面的this就是指代A,而且函數的參數只有一個,返回的是一個Pair對象,this指代A,that就是傳入的B類型對象。

  • to函數建立Pair對象,而後能夠用解構聲明展開

注意: 說明一下中綴調用和解構聲明是兩個不一樣的概念,沒有必然關係,只能說中綴調用返回的一個對象可使用解構聲明把他們展開,在展開圖中是解構相等的。例如圖上的to函數返回的是一個Pair()對象,Pair對象支持解構聲明,而後to函數返回對象和解構後的對象相等。

7.2 into函數自定義中綴調用

  • 源碼分析
infix fun <T> T.into(other: Collection<T>): Boolean = other.contains(this)
複製代碼

分析: 使用infix關鍵字修飾的函數,泛型T對象元素是否存在於泛型T集合之中。「T.into(Collection<T>)」結構,實際也是一種帶接收者結構,this也就是指代了into函數前面調用T類型對象。

8、中綴調用應注意哪些問題

  • 一、前面所講to, into,sameAs實際上就是函數調用,若是把infix關鍵字去掉,那麼也就純粹按照函數調用方式來。好比1.to("A"), element.into(list)等,只有加了中綴調用的關鍵字infix後,纔可使用簡單的中綴調用例如 1 to "A", element into list等

  • 二、並非全部的函數都能寫成中綴調用,中綴調用首先必須知足一個條件就是函數的參數只有一個。而後再看這個函數的參與者是否是隻有兩個元素,這兩個元素能夠是兩個數,能夠是兩個對象,能夠是集合等。

9、Kotlin中的解構聲明

9.1 解構聲明概述

解構聲明是把一個對象當作一組單獨的變量,有時候咱們把一個對象當作一組單獨的變量管理會變得更加簡單。注意: 支持解構聲明的對象的類必須是數據類(使用data關鍵字修飾的類),由於只有data class纔會生成對應的component()方法(這個會在後續中講解到),data class中的每一個屬性都會有對應的component()方法對應

9.2 解構聲明基本使用

  • 先定義一個data class
package com.mikyou.kotlin.destruct

/** * Created by mikyou on 2018/4/10. */
data class Student(var name: String, var age: Int, var grade: Double)
複製代碼
  • 解構聲明調用
package com.mikyou.kotlin.destruct

/** * Created by mikyou on 2018/4/10. */
fun main(args: Array<String>) {
    val student = Student("mikyou", 18, 99.0)
    val (name, age, grade) = student//將一個student對象解構成一組3個單獨的變量
    println("my name is $name , I'm $age years old, I get $grade score")//解構後的3個變量能夠脫離對象,直接單獨使用

}
複製代碼

9.3 解構聲明實質原理

解構聲明實際上就是將對象中全部屬性,解構成一組屬性變量,並且這些變量能夠單獨使用,爲何能夠單獨使用,是由於每一個屬性值的得到最後都編譯成經過調用與之對應的component()方法,每一個component()方法對應着類中每一個屬性的值,而後在做用域定義各自屬性局部變量,這些局部變量存儲着各自對應屬性的值,因此看起來變量能夠單獨使用,實際上使用的是局部變量。以下反編譯成的Java代碼

package com.mikyou.kotlin.destruct;

import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;

@Metadata(
   mv = {1, 1, 9},
   bv = {1, 0, 2},
   k = 2,
   d1 = {"\u0000\u0014\n\u0000\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\u0011\n\u0002\u0010\u000e\n\u0002\b\u0002\u001a\u0019\u0010\u0000\u001a\u00020\u00012\f\u0010\u0002\u001a\b\u0012\u0004\u0012\u00020\u00040\u0003¢\u0006\u0002\u0010\u0005¨\u0006\u0006"},
   d2 = {"main", "", "args", "", "", "([Ljava/lang/String;)V", "production sources for module Function"}
)
public final class DestructTestKt {
   public static final void main(@NotNull String[] args) {
      Intrinsics.checkParameterIsNotNull(args, "args");
      Student student = new Student("mikyou", 18, 99.0D);
      String name = student.component1();//對應的component1()方法,返回對應就是Student中name屬性,並賦值給建立局部變量name
      int age = student.component2();//對應的component2()方法,返回對應就是Student中age屬性, 並賦值給建立局部變量age
      double grade = student.component3();//對應的component3()方法,返回對應就是Student中屬性,並賦值給建立局部變量grade
      String var6 = "my name is " + name + " , I'm " + age + " years old, I get " + grade + " score";
      System.out.println(var6);//注意: 這裏單獨使用的name, age, grade其實是局部變量
   }
}

複製代碼

9.4 解構聲明應注意的問題

  • 一、解構聲明中解構對象的屬性是可選的,也就是並非要求該對象中全部屬性都須要解構,也就是可選擇須要解構的屬性。可使用下劃線"_"省略不須要解構的屬性也能夠不寫改屬性直接忽略。注意: 雖然二者做用是同樣的,可是最後生成component()方法不同,使用下劃線的會佔用compoent1()方法,age直接從component2()開始生成, 直接不寫name,age會從component1()方法開始生成。例如

下劃線_ 忽略name屬性例子

package com.mikyou.kotlin.destruct

/** * Created by mikyou on 2018/4/10. */
fun main(args: Array<String>) {
    val student = Student("mikyou", 18, 99.0)
    val (_, age, grade) = student//下劃線_ 忽略name屬性
    println("I'm $age years old, I get $grade score")//解構後的3個變量能夠脫離對象,直接單獨使用
}

//下劃線_ 忽略name屬性 反編譯後Java代碼
package com.mikyou.kotlin.destruct;

import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;

@Metadata( mv = {1, 1, 9}, bv = {1, 0, 2}, k = 2, d1 = {"\u0000\u0014\n\u0000\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\u0011\n\u0002\u0010\u000e\n\u0002\b\u0002\u001a\u0019\u0010\u0000\u001a\u00020\u00012\f\u0010\u0002\u001a\b\u0012\u0004\u0012\u00020\u00040\u0003¢\u0006\u0002\u0010\u0005¨\u0006\u0006"}, d2 = {"main", "", "args", "", "", "([Ljava/lang/String;)V", "production sources for module Function"} )
public final class DestructTestKt {
   public static final void main(@NotNull String[] args) {
      Intrinsics.checkParameterIsNotNull(args, "args");
      Student student = new Student("mikyou", 18, 99.0D);
      int age = student.component2();//name會佔用component1()方法,可是沒有生成,因此age從component2()方法開始
      double grade = student.component3();
      String var5 = "I'm " + age + " years old, I get " + grade + " score";
      System.out.println(var5);
   }
}

複製代碼

直接不寫name屬性例子

package com.mikyou.kotlin.destruct

/** * Created by mikyou on 2018/4/10. */
fun main(args: Array<String>) {
    val student = Student("mikyou", 18, 99.0)
    val (age, grade) = student//直接不寫name屬性
    println("I'm $age years old, I get $grade score")//解構後的3個變量能夠脫離對象,直接單獨使用
}

//直接不寫name屬性 反編譯後Java代碼
package com.mikyou.kotlin.destruct;

import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;

@Metadata( mv = {1, 1, 9}, bv = {1, 0, 2}, k = 2, d1 = {"\u0000\u0014\n\u0000\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\u0011\n\u0002\u0010\u000e\n\u0002\b\u0002\u001a\u0019\u0010\u0000\u001a\u00020\u00012\f\u0010\u0002\u001a\b\u0012\u0004\u0012\u00020\u00040\u0003¢\u0006\u0002\u0010\u0005¨\u0006\u0006"}, d2 = {"main", "", "args", "", "", "([Ljava/lang/String;)V", "production sources for module Function"} )
public final class DestructTestKt {
   public static final void main(@NotNull String[] args) {
      Intrinsics.checkParameterIsNotNull(args, "args");
      Student student = new Student("mikyou", 18, 99.0D);
      String age = student.component1();//直接不寫name,而後age從component
      int grade = student.component2();
      String var4 = "I'm " + age + " years old, I get " + grade + " score";
      System.out.println(var4);
   }
}

複製代碼
  • 二、解構聲明的對象類型必定是data class,普通的class是不會生成對應的component的方法。

歡迎關注Kotlin開發者聯盟,這裏有最新Kotlin技術文章,每週會不按期翻譯一篇Kotlin國外技術文章。若是你也喜歡Kotlin,歡迎加入咱們~~~

相關文章
相關標籤/搜索