亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Kotlin學習教程之函數的默認參數

 更新時間:2020年11月09日 11:42:11   作者:fb0122  
這篇文章主要給大家介紹了關于Kotlin學習教程之函數的默認參數,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前言

​ 在Java中,為函數的參數添加默認值是不被允許的,這是為了防止默認參數與函數重載同時使用時二義性的問題,考慮下面的例子:

void func(p1: String, p2: String, p3: String = "default") {
	// do something
}

void func(String p1, String p2) {
	// do something
}

假設上面的代碼是可以編譯通過的,那么當調用func("p1","p2") 時,編譯器會不知道到底該調用哪個方法。所以Java是不支持默認參數的,但是依然可以通過函數重載的方式實現(xiàn)默認參數的功能,這也是我們最普遍使用的方式:

void func(String p1, String p2, String p3) {
	// do something
}

void func(String p1, String p2) {
	func(a, b, "default");
}

通過上述函數重載的方式,也可以實現(xiàn)默認參數,但是有個問題也很明顯,就是如果要支持默認參數,我們需要寫很多的模版代碼,好像也不是那么方便。然而,Kotlin 提供了默認參數的支持,接下來看看Kotlin中對于默認參數的支持是怎樣的,又是怎么解決我們開始提到的那個二義性的問題的。

使用

在Kotlin中,使用默認參數也很簡單,在函數定義中直接賦值即可:

fun func(p1: String, p2: String, p3: String = "default") {
	// do something
}

上述函數定義中,c 的默認值就是default,可以這樣去調用 func("p1","p2")。同樣的,針對構造函數,也可以指定默認值:

class TestDefaultParameters (
 val name: String,
 val type: String = "default"
){}

那么如果想要在Java中調用kotlin帶有默認參數的函數怎么做呢?如果在Java中直接調用func("p1","p2")編譯器會報錯,這是需要給kotlin的方法加上Jvm重載的注解就可以了:

@JvmOverloads
fun func(p1: String, p2: String, p3: String = "default") {
	// do something
}

解析

接下來,我們看看Kotlin是如何實現(xiàn)默認參數的,首先,寫一個例子如下:

fun main(args: Array<String>) {
 val testDefaultParameters = TestDefaultParameters("")
 testDefaultParameters.func("position1", "position2")
}

class TestDefaultParameters (
 val name: String,
 val type: String = "default"
){
 @JvmOverloads
 fun func(p1: String, p2: String, p3: String = "default") {
  // do something
 }

}

將上述的func的函數定義Decompile為Java實現(xiàn):

@JvmOverloads
public final void func(@NotNull String p1, @NotNull String p2, @NotNull String p3) {
 Intrinsics.checkParameterIsNotNull(p1, "p1");
 Intrinsics.checkParameterIsNotNull(p2, "p2");
 Intrinsics.checkParameterIsNotNull(p3, "p3");
}

// $FF: synthetic method
public static void func$default(TestDefaultParameters var0, String var1, String var2, String var3, int var4, Object var5) {
 if ((var4 & 4) != 0) {
 	var3 = "default";
	}
	var0.func(var1, var2, var3);
}

@JvmOverloads
public final void func(@NotNull String p1, @NotNull String p2) {
	func$default(this, p1, p2, (String)null, 4, (Object)null);
}
...
// 調用func函數
TestDefaultParameters.func$default(testDefaultParameters, "position1", "position2", (String)null, 4, (Object)null);

中間一些代碼我省略了,可以看到,Kotlin編譯器為我們生成了三個func的重載方法,下面我們依次來看一下分別都是什么函數:

  • 首先看到的第一個函數是帶有三個參數的func,函數內部都做了空安全的檢查,這是kotlin的特性,由于聲明函數時參數都是不為空的,所以這里需要檢查參數是否為空,會拋出異常。
  • 第二個函數我們看到名字是func$default, 并不是func的方法重載,而是一個新的方法,這就是默認參數實現(xiàn)的關鍵方法,這里暫且按下不表,后面詳細講解。
  • 第三個函數依然是func方法的重載,可以看到這個方法只有兩個參數,并且內部調用了第二個方法。其實這個方法是給Java調用的,由于我們將func函數聲明為@JvmOverloads,所以當Java在不傳遞默認參數調用func的時候,實際上調用的是這個方法。如果將@JvmOverloads去掉的話,是沒有這個方法的。

在了解了三個方法的作用之后,主要來看一下第二個方法:

// $FF: synthetic method
public static void func$default(TestDefaultParameters var0, String var1, String var2, String var3, int var4, Object var5) {
 if ((var4 & 4) != 0) {
 	var3 = "default";
	}
	var0.func(var1, var2, var3);
}

可以看到這個方法有6個參數,var0為Class對象,var1 ~var3 分別對應func函數的三個參數,然后有一個int類型的var4和一個Object類型的 var5。var5這個大多數情況下都為null,默認參數實現(xiàn)的秘密主要是在這個var 4上, 來看看當調用函數使用默認參數時,是怎么調用的:

// kotlin
func("position1", "position2")
 
// Decompile
func$default(testDefaultParameters, "position1", "position2", (String)null, 4, (Object)null)

看到var4的值為4。是由于原函數是第三個參數為默認參數,即 position = 2位置的參數,所以 var4 = 222^222=4
在看之前func$default 的方法實現(xiàn):

if ((var4 & 4) != 0) {
 var3 = "default";
}

當var4 & 4 != 0的時候,var3的值就等于默認參數??梢园l(fā)現(xiàn),func$default函數的int類型的參數就是表示第幾個參數的值是默認參數的。下面看一個稍微復雜的例子:

fun func(p1: String = "position1", p2: String = "position2", p3: String = "position3") {
   // do something
}

// 調用
testDefaultParameters.func(p2 = "position2")

這次三個參數都有默認值,且調用時用具名參數指定p2的值為"position2"。下面看看Decompile后的代碼:

// $FF: synthetic method
public static void func$default(TestDefaultParameters var0, String var1, String var2, String var3, int var4, Object var5) {
if ((var4 & 1) != 0) {
 var1 = "position1";
}

if ((var4 & 2) != 0) {
 var2 = "position2";
}

if ((var4 & 4) != 0) {
 var3 = "position3";
}

 var0.func(var1, var2, var3);
}

// 調用
func$default(testDefaultParameters, (String)null, "position2", (String)null, 5, (Object)null)

可以看到,這次方法體內有三個判斷,因為有三個參數都是有默認值的,傳遞的參數為5,是由于函數調用時,index=0 和 index=2的參數為默認參數,所以 var4 = 20+222^0 + 2^220+22 = 5。

這里大概解釋一下為什么要這么設計的原因:
當寫有多個條件,例如權限判斷,index判斷等邏輯的時候非常適合位運算。例如在上面的例子中,參數的index可以表示為:2的index冪的二進制數,例如 index = 0 即 202^020 , 用二進制表示為:0001,index = 1 即 212^121 ,表示為:0010(可以看作是二進制數中1的位置,即表示index)。
那么如果多個位置比如index=0與index=2呢?既可以表示為:0101。就是 20+22=52^0 + 2^2 = 520+22=5 。與目標所在的index進行按位與運算的時候,如果不等于0就表示該index符合條件。否則不符合。

回過頭來看上述func$default函數體就清晰了,就是通過位置判斷,當不是使用默認值的位置時,就不使用默認值。

上述例子中,我們看到含有默認值的參數的函數在Decompile之后,有一個始終為null的Object參數,而且也沒有被使用到。那么這個參數有什么用呢?這個參數會在嘗試重寫有默認參數的函數時用到。例如下面的例子:

open class TestDefaultParameters {
  open fun func(p1: String = "position1", p2: String = "position2", p3: String = "position3") {
    // do something
  }
}

class TestDefaultChild : TestDefaultParameters() {
  override fun func(p1: String, p2: String, p3: String) {
    // do something
  }
}

將上述代碼編譯一下:

// $FF: synthetic method
public static void func$default(TestDefaultParameters var0, String var1, String var2, String var3, int var4, Object var5) {
  if (var5 != null) {
    throw new UnsupportedOperationException("Super calls with default arguments not supported in this target, function: func");
  } else {
    if ((var4 & 1) != 0) {
     var1 = "position1";
    }

    if ((var4 & 2) != 0) {
     var2 = "position2";
    }

    if ((var4 & 4) != 0) {
     var3 = "position3";
    }

    var0.func(var1, var2, var3);
}
}

可以看到,當調用超類使用默認參數在當前版本是不允許的(以后可能允許)。這就是Object參數的用處。

總結

以上就是對kotlin的默認參數實現(xiàn)的一些總結。

到此這篇關于Kotlin學習教程之函數的默認參數的文章就介紹到這了,更多相關Kotlin函數的默認參數內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Cocos2d-x 3.0中集成社交分享ShareSDK的詳細步驟和常見問題解決

    Cocos2d-x 3.0中集成社交分享ShareSDK的詳細步驟和常見問題解決

    這篇文章主要介紹了Cocos2d-x 3.0中集成社交分享ShareSDK的詳細步驟和常見問題的解決方法以及需要注意的問題,需要的朋友可以參考下
    2014-04-04
  • Android編程實現(xiàn)異步消息處理機制的幾種方法總結

    Android編程實現(xiàn)異步消息處理機制的幾種方法總結

    這篇文章主要介紹了Android編程實現(xiàn)異步消息處理機制的幾種方法,結合實例形式詳細總結分析了Android異步消息處理機制的原理、相關實現(xiàn)技巧與操作注意事項,需要的朋友可以參考下
    2018-08-08
  • Android實現(xiàn)本地上傳圖片并設置為圓形頭像

    Android實現(xiàn)本地上傳圖片并設置為圓形頭像

    我們在做項目的時候會用到圓形的圖片,比如用戶頭像,類似QQ。用戶在用QQ更換頭像的時候,上傳的圖片都是矩形的,但顯示的時候確是圓形的。那么這是如何實現(xiàn)的呢,下面我們就來探討下吧。
    2015-05-05
  • 使用DrawerLayout組件實現(xiàn)側滑抽屜的功能

    使用DrawerLayout組件實現(xiàn)側滑抽屜的功能

    DrawerLayout組件同樣是V4包中的組件,也是直接繼承于ViewGroup類,所以說是一個容器類,下面通過本文給大家介紹使用DrawerLayout組件實現(xiàn)側滑抽屜的功能,感興趣的朋友一起看下吧
    2016-08-08
  • RxJava2.x實現(xiàn)定時器的實例代碼

    RxJava2.x實現(xiàn)定時器的實例代碼

    本篇文章主要介紹了RxJava2.x實現(xiàn)定時器,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • 詳解Android?Flutter如何使用相機實現(xiàn)拍攝照片

    詳解Android?Flutter如何使用相機實現(xiàn)拍攝照片

    在app中使用相機肯定是再平常不過的一項事情了,相機肯定涉及到了底層原生代碼的調用,那么在flutter中如何快速簡單的使用上相機的功能呢?一起來看看吧
    2023-04-04
  • Android實現(xiàn)手機監(jiān)控攝像頭

    Android實現(xiàn)手機監(jiān)控攝像頭

    這篇文章主要為大家詳細介紹了Android實現(xiàn)手機監(jiān)控攝像頭,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Android自定義控件仿QQ抽屜效果

    Android自定義控件仿QQ抽屜效果

    這篇文章主要為大家詳細介紹了Android自定義控件仿QQ抽屜效果的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • Android NDK開發(fā)入門

    Android NDK開發(fā)入門

    本文主要對NDK產生的背景、使用NDK原因、NDK簡介、NDK開發(fā)環(huán)境的搭建、如何運行NDK提供的事例demo等進行了詳細的介紹。具有很好的參考價值,需要的朋友一起來看下吧
    2016-12-12
  • Android側滑菜單之DrawerLayout用法詳解

    Android側滑菜單之DrawerLayout用法詳解

    今天小編就為大家分享一篇關于Android側滑菜單之DrawerLayout用法詳解,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03

最新評論