Kotlin 基礎篇二

先來了解下集合初始化的方式

listOf創(chuàng)建的集合是一個<u>不可變的集合</u>策菜,也就是不能調用添加或者刪除的方法具钥。

//聲明一個list
val list= listOf("唐三","小舞","馬紅俊","戴沐白","朱竹清","奧斯卡","寧榮榮")

下面創(chuàng)建的集合是可變的微服。類似的set集合的創(chuàng)建方式是一樣的葡兑,set集合不允許重復元素镀娶。對應的方式是setOf立膛、mutableSetOf

val list= mutableListOf("唐三","小舞","馬紅俊","戴沐白","朱竹清","奧斯卡","寧榮榮");
list.add("白沉香")

map 的聲明和添加數(shù)據(jù)方式,以及遍歷數(shù)據(jù)梯码。

val map=HashMap<String,Int>()
map["唐三"]=1;
map["小舞"]=2;
map["戴沐白"]=3;

for ((name,number) in map){
    println("name is $name,number is $number")
}

也可以這樣定義初始化map集合

//這個方式定義的map同樣是不能修改的 
val map = mapOf("唐三" to 1,"小舞" to 2,"戴沐白" to 3) 

跟list一樣宝泵,如果需要修改map的數(shù)據(jù),像這樣定義map轩娶,就可以添加或者刪除數(shù)據(jù)

val map= mutableMapOf("唐三" to 1,"小舞" to 2,"戴沐白" to 3)
map["朱竹清"]=4

下面來看Lambda的使用

<u>Lambda 就是一小段可以作為參數(shù)傳遞的代碼</u>儿奶,這一小段代碼不宜過長,否則會影響可讀性鳄抒。

<u>Lambda語法結構{參數(shù)名1:參數(shù)類型闯捎,參數(shù)名2:參數(shù)類型->函數(shù)體}</u>,最后一行代碼會自動作為Lambda表達式的返回值许溅。

//獲取長度最長的人名
 val list= mutableListOf("唐三" ,"小舞" ,"戴沐白" )
 val maxLength=list.maxByOrNull { name : String -> name.length }
 println("maxLength is $maxLength")

由于Kotlin出色的類型推到機制瓤鼻,Lambda表達式中參數(shù)的類型可以省略,上面的代碼可以簡化

//由于出色的類型推到機制贤重,上面的類型可以簡化
val maxLength=list.maxByOrNull { name -> name.length }

當Lambda表達式的參數(shù)列表只有一個的時候茬祷,也可以不必聲明參數(shù)名,而是可以使用it代替并蝗,進一步簡化

val maxLength=list.maxByOrNull { it.length }

上面的這種方式就是函數(shù)式API語法結構

集合中的map函數(shù)是最常用的一種函數(shù)式API祭犯,它用于將集合中的每一個元素都映射成另外一個值,映射的規(guī)則在Lambda表達式中指定滚停,最終生成一個新的集合

val list= listOf("tang san","xiao wu","dai mu bai","zhu zhu qing","ao si ka")
val newList=list.map { it.uppercase(Locale.CHINA) }
for (name in newList){
     println("name is $name")
 }

另外一個函數(shù)式API-filter沃粗,它是用來過濾集合中的數(shù)據(jù)的,它可以單獨使用也可以配合map一起使用键畴。

val list= listOf("tang san","xiao wu","dai mu bai","zhu zhu qing","ao si ka")
val newList=list.filter { it.length>8 }.map { it.uppercase() }
for (name in newList){
    println("name is $name")
}

先使用filter進行條件篩選最盅,然后再轉成大寫,順序可以調換镰吵。

函數(shù)值API--any 和 all檩禾,any表示是否存在,all表示是否全部是疤祭,這兩個是條件判斷盼产,返回true and false

//函數(shù)值API any all
val list= listOf("tang san","xiao wu","dai mu bai","zhu zhu qing","ao si ka")
val any = list.any { it.length > 8 }
val all = list.all { it.length > 8 }
println("any is $any , all is $all")  //any is true , all is false

java函數(shù)式API調用

如果在kotlin中調用一個java方法,并且該方法接收一個java單抽象方法接口參數(shù)勺馆,就可以使用函數(shù)式API戏售。

Thread { println("do some thing") }.start()

Thread 里邊需要一個參數(shù) Runnable 侨核,Runnable里邊只有一個抽象run方法,所以可以直接省略這些灌灾。

val editText = EditText(context)
editText.addTextChangedListener(object : TextWatcher {
    override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
    override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
    override fun afterTextChanged(editable: Editable) {}
})

參數(shù)有多個抽象方法需要實現(xiàn)搓译,不能省略,書寫格式是這樣的锋喜。

空指針檢查

下面的函數(shù)些己,當調用的時候,是不能傳遞null參數(shù)的嘿般,直接會編譯不過去

fun readBooks(study: Study){
    study.readBooks()
}

Kotlin利用編譯判空檢查機制幾乎杜絕了空指針的異常段标,如果業(yè)務邏輯需要傳null的場景,可以定義可以為null的參數(shù)類型

  override fun onClick(v: View?) {
        when (v?.id) {
            R.id.iv_create_pci_finish -> picFinish()
        }
  }

這樣就可以傳null了炉奴,但是這樣寫依然編譯不過去逼庞,因為傳遞的參數(shù)可能會null就需要添加null判斷

Int? 可為null的整形 Int 不可為null的整形

String表示不可null的字符串 String?可為null的字符串

瞻赶?.操作符

這個操作符表示不為null正常調用某個方法赛糟,當對象為null則什么都不做。

?:操作符

這個操作符兩邊都接收一個表達式砸逊,如果左邊的表達式不為null就返回左邊的表達式璧南,否則返回右邊的表達式

val c = a ?: b  
這個表達式相當于
  val c = if (a != null) {
        a
    } else {
        b
    }

!!操作符

如果一個對象可能會null,這個時候這個對象調用某個方法編譯不會通過痹兜,如果不想添加判null操作穆咐,可以使用這個操作符!!,表示告訴kotlin字旭,這個對象我非常確信不為null (感覺這個操作符沒啥用,直接加判null就好了)

//參數(shù)是一個可能會null的對象,這個時候如果不想添加判null需要編譯通過就需要使用!!這個操作符
 mVideoFragment!!.seekTimeline(
            timestamp,
            NvsStreamingContext.STREAMING_ENGINE_SEEK_FLAG_SHOW_ANIMATED_STICKER_POSTER
       )

let函數(shù)崖叫,屬于kotlin的標準函數(shù)

let函數(shù)提供了函數(shù)式API的編程接口遗淳,并將原始調用對象作為參數(shù)傳遞到Lambda表達式中,let函數(shù)配合心傀?.操作符非常好用

mTimelineEditor?.let {
    it.setSequencLeftPadding(sequenceLeftPadding)
    it.setSequencRightPadding(halfScreenWidth)
    it.setTimeSpanLeftPadding(sequenceLeftPadding)
}

字符串的內嵌表達式

之前打印數(shù)據(jù)的時候已經涉及到了屈暗,比如之前的打印表達式

"any is $any , all is $all"

函數(shù)的參數(shù)默認值

fun test(num:Int,name:String="Tom"){
    println("num is $num, name is $name")
}

test(1) //這樣調用是合法的

這個函數(shù)第二個參數(shù)有一個默認值,那么調用這個函數(shù)的時候脂男,可以只傳遞第一個參數(shù)养叛,也可以兩個都傳遞

fun test(name:String="Tom",num:Int){
    println("num is $num, name is $name")
}

test(num=1) //通過鍵值對的方式傳遞參數(shù)就可以調用了

如果第一個參數(shù)是帶默認值,直接像test(1)就會報錯宰翅,kotlin認為配型不匹配弃甥。這個問題可以使用鍵值對的方式進行傳值,這個也是允許的

Kotlin 另外幾個常用的標準函數(shù)

with汁讼、run淆攻、aplly這幾個標準函數(shù)在開發(fā)中會經常使用到阔墩,kotlin中的標準函數(shù)是指在Standard.kt文件中定義的函數(shù),任何Kotlin的代碼都可以隨便調用使用瓶珊。

with函數(shù)接收兩個參數(shù)啸箫,第一個參數(shù)是任意類型的對象,第二個參數(shù)是一個Lambda表達式伞芹,with函數(shù)會在Lambda表達式中提供第一個參數(shù)的對象的上下文忘苛,并使用Lambda表達式最后一行的表達式作為返回值。

NvsStreamingContext.SdkVersion sdkVersion = mStreamingContext.getSdkVersion();
StringBuilder stringBuilder = new StringBuilder("V ");
stringBuilder.append(sdkVersion.majorVersion);
stringBuilder.append(".");
stringBuilder.append(sdkVersion.minorVersion);
stringBuilder.append(".");
stringBuilder.append(sdkVersion.revisionNumber);
mSDKVersion.setText(stringBuilder.toString());

上面是sdk demo中的代碼唱较,如果使用with函數(shù)進行改造

NvsStreamingContext.SdkVersion sdkVersion = mStreamingContext.getSdkVersion();
val result=with(StringBuilder()){
    append("V ")
    append(sdkVersion.majorVersion)
    append(".")
    append(sdkVersion.minorVersion)
    append(".")
    append(sdkVersion.revisionNumber)
    toString()
}
mSDKVersion.setText(result);

使用with函數(shù)代碼變的更加精簡

run函數(shù)

這個函數(shù)跟with函數(shù)類似扎唾,得到的結果也相似。

val result=StringBuilder().run{
    append("V ")
    append(sdkVersion.majorVersion)
    append(".")
    append(sdkVersion.minorVersion)
    append(".")
    append(sdkVersion.revisionNumber)
    toString()
}
mSDKVersion.setText(result);

aplly函數(shù)

這個函數(shù)跟run函數(shù)類型绊汹,但是最后一行不是返回值稽屏,而是返回對象本身,下面是一個實際應用的例子。

 mStartNextActivity.setOnClickListener {
            val intent=Intent(this,OtherActivity::class.java).apply {
                putExtra("param1",1)
                putExtra("param2","2")
                putExtra("param1",1)
            }
            startActivity(intent)
        }

kotlin中定義靜態(tài)方法

相比于java西乖,kotlin中因為單例很簡單狐榔,弱化靜態(tài)方法的概念。像java中的工具類Kotlin中推薦直接使用單例進行實現(xiàn)获雕。

object Utils {

    private const val MIN_DELAY_TIME = 1000
    private var lastClickTime: Long = 0

    /**
     *兩次點擊間隔不能少于1000ms
     * The interval between two clicks cannot be less than 1000ms
     */
    fun isFastClick(): Boolean {
        var flag = true
        val currentClickTime = System.currentTimeMillis()
        if (currentClickTime - lastClickTime >= MIN_DELAY_TIME) {
            flag = false
        }
        lastClickTime = currentClickTime
        return flag
    }
}

這樣處理之后薄腻,里邊所有的方法就可以像靜態(tài)方法那樣調用了。

如果某個類里邊届案,有對象方法也想要靜態(tài)方法怎么辦庵楷?可以使用companion object

class Utils {

    companion object{
        private val MIN_DELAY_TIME = 1000
        private var lastClickTime: Long = 0
        /**
         *兩次點擊間隔不能少于1000ms
         * The interval between two clicks cannot be less than 1000ms
         */
        fun isFastClick(): Boolean {
            var flag = true
            val currentClickTime = System.currentTimeMillis()
            if (currentClickTime - lastClickTime >= MIN_DELAY_TIME) {
                flag = false
            }
            lastClickTime = currentClickTime
            return flag
        }

    }
   
    
    fun doAction(){
        Log.e("Utils","doAction")
    }
}

像上面這樣編寫就能解決上面的問題,isFastClick這個方法仍然可以像靜態(tài)方法那樣調用楣颠,doaction就是一個對象方法尽纽。但是這樣處理在原理上isFastClick并不是一個靜態(tài)方法,companion object這個關鍵字會在Utils類中創(chuàng)建伴生類童漩,kotlin保證只會存在一個伴生類弄贿。

如果想要定義真正意義的靜態(tài)方法,kotlin提供了兩個方式:注解和頂層方法矫膨。

companion object只是在語法上模擬了靜態(tài)方法的調用方式差凹,如果加上@JvmStatic注解,那么kotlin編譯器會將這個方法編譯成真正的靜態(tài)方法侧馅。

class Utils {

    companion object{
        private val MIN_DELAY_TIME = 1000
        private var lastClickTime: Long = 0
        /**
         *兩次點擊間隔不能少于1000ms
         * The interval between two clicks cannot be less than 1000ms
         */
        @JvmStatic
        fun isFastClick(): Boolean {
            var flag = true
            val currentClickTime = System.currentTimeMillis()
            if (currentClickTime - lastClickTime >= MIN_DELAY_TIME) {
                flag = false
            }
            lastClickTime = currentClickTime
            return flag
        }

    }


    fun doAction(){
        Log.e("Utils","doAction")
    }
}

這樣isFastClick就是真正意義上的靜態(tài)方法了危尿。@JvmStatic 這個注解不能加在普通方法中會報錯。

kotlin頂層方法

頂層方法是指馁痴,沒有定義在任何類中的方法谊娇。在kotlin中創(chuàng)建Kotlin file ,在file中定義的方法都是靜態(tài)方法弥搞,全局可以調用也是真正意義的靜態(tài)方法邮绿,全局可以調用航攒。

延遲初始化

private var mTimeline: NvsTimeline? = null

這是聲明全局變量的方式炕柔,如果這樣初始化羡亩,那么在使用mTimeline這個對象的時候需要頻繁的使用唱逢?.進行判空操作,否則編譯不過去挖胃,由于kotlin編譯機制就不得不編寫大量額外的判空操作杂靶。

如何解決這個問題呢?延時初始化lateinit使用這個關鍵字修飾全局變量酱鸭,這樣聲明的變量不為null吗垮,使用的時候可以避免頻繁的判空操作。

private lateinit var mTimeline: NvsTimeline

但是這個關鍵字本身是有風險的凹髓,如果使用之前沒有初始化會拋異常烁登,所以當對一個全局的變量使用了lateinit關鍵字,請確保它在被任何地方調用之前已經初始化蔚舀。

在使用全局變量之前可以通過代碼來判斷全部變量是否已經初始化饵沧,::mTimeline.isInitialized這個就是判斷對象是否會null的方法。

if(!::mTimeline.isInitialized){
    mTimeline=initTimeline()
}

擴展函數(shù)

擴展函數(shù)表示在不修改某個類源碼的基礎上赌躺,仍然可以打開這個類狼牺,向該類添加新方法。

擴展函數(shù)的語法結構

fun ClassName.methodName(param1:Int,Param2:Int):Int{
    return 0;
}

擴展函數(shù)可以放在頂層函數(shù)礼患,這樣擴展函數(shù)就擁有了全局的訪問域是钥。

fun String.lowersCount():Int{
    var count=0
    for (low in this){
        if (low.isLowerCase()){
            count++
        }
    }
    return count
}
   //測試方法
  val lowNum="asdWERff".lowersCount()
  println("lowNum is $lowNum ")
   //輸出日志
  //lowNum is 5   

上面是給String定義的一個統(tǒng)計小寫字母個數(shù)的方法,這個在String類里邊是沒有的缅叠。利用這個特性悄泥,可以寫出豐富多樣的擴展函數(shù),非常好用肤粱。擴展函數(shù)在kotlin中沒有任何限制码泞,可以再任何類上添加擴展函數(shù),這將大大提升代碼質量和研發(fā)效率狼犯。


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市领铐,隨后出現(xiàn)的幾起案子悯森,更是在濱河造成了極大的恐慌,老刑警劉巖绪撵,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瓢姻,死亡現(xiàn)場離奇詭異,居然都是意外死亡音诈,警方通過查閱死者的電腦和手機幻碱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門绎狭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人褥傍,你說我怎么就攤上這事儡嘶。” “怎么了恍风?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵蹦狂,是天一觀的道長。 經常有香客問我朋贬,道長凯楔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任锦募,我火速辦了婚禮摆屯,結果婚禮上,老公的妹妹穿的比我還像新娘糠亩。我一直安慰自己虐骑,他們只是感情好,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布削解。 她就那樣靜靜地躺著富弦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪氛驮。 梳的紋絲不亂的頭發(fā)上腕柜,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天,我揣著相機與錄音矫废,去河邊找鬼盏缤。 笑死,一個胖子當著我的面吹牛蓖扑,可吹牛的內容都是我干的唉铜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼律杠,長吁一口氣:“原來是場噩夢啊……” “哼潭流!你這毒婦竟也來了?” 一聲冷哼從身側響起柜去,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤灰嫉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后嗓奢,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體讼撒,經...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了根盒。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钳幅。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖炎滞,靈堂內的尸體忽然破棺而出敢艰,到底是詐尸還是另有隱情,我是刑警寧澤厂榛,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布盖矫,位于F島的核電站,受9級特大地震影響击奶,放射性物質發(fā)生泄漏辈双。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一柜砾、第九天 我趴在偏房一處隱蔽的房頂上張望湃望。 院中可真熱鬧,春花似錦痰驱、人聲如沸证芭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽废士。三九已至,卻和暖如春蝇完,著一層夾襖步出監(jiān)牢的瞬間官硝,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工短蜕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留氢架,地道東北人。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓朋魔,卻偏偏與公主長得像岖研,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子警检,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內容