kotlin 零散筆記

裝箱

基本類型的數組 是沒有自動裝箱拆箱的過程,而list是有的 

對於基本類型使用,推薦用數組,性能會好點

kotlin裝箱須要根據場合

對於 Int 這樣的基本類型,儘可能用不可空變量
var a: Int = 1 // unbox
var b: Int? = 2 // box    會轉成  Integer.parse(2) 執行裝箱
var list: List<Int> = listOf(1, 2) // box
知足如下條件就不會執行裝箱
1 不可空類型
2 使用 IntArray FloatArray複製代碼

數組寫法

kotlin 數組不支持協變 就是子類數組對象不能賦值給父類的數組變量

在kotlin 數組的寫法變成 泛型式寫法   arrayOf("","","")

var array: IntArray = intArrayOf(1, 2) //這種是 unbox 的

kotlin 裏用專門的基本類型數組類 (IntArray FloatArray LongArray) 才能夠免於裝箱拆箱。

元素不是基本類型時,相比 Array,用 List 更方便些
複製代碼

集合

支持協變 指的是:子類類型的list 能夠賦值給父類的list

List 以固定順序存儲一組元素,元素能夠重複。    ===>listOf("a", "b", "c") 支持協變

Set 存儲一組互不相等的元素,一般沒有固定 順序.  ===>setOf("a", "b", "c")  支持協變

Map 存儲 鍵-值對的數據集合,鍵互不相等,但不一樣的鍵能夠對應相同的值。

var map = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key4" to 3)
map.put("key1", 2)
map["key1"] = 2  
val value1 = map.get("key1")               
val value2 = map["key2"]
操做函數: forEach filter map flamap
惰性集合sequenceOf    只有使用的使用時候纔會執行複製代碼


用數組仍是list

list相對於數組 功能更豐富,可是數組基本類型的數組是沒有自動裝拆箱過程,而list是有的,

對於基本類型  ,數組的性能會比list好. 

在kotlin ,要用專門的數組類才能免於自動裝拆箱 (IntArray FloatArray LongArray)複製代碼

可變集合/不可變集合

集合分爲兩種類型:只讀的和可變的。這裏的只讀有兩層意思:
java

  • 集合的 size 不可變
  • 集合中的元素值不可變

如下是三種集合類型建立不可變和可變實例的例子:數組

  • listOf() 建立不可變的 ListmutableListOf() 建立可變的 List
  • setOf() 建立不可變的 SetmutableSetOf() 建立可變的 Set
  • mapOf() 建立不可變的 MapmutableMapOf() 建立可變的 Map
不可變的 能夠經過 toMutable*() 系函數轉換成可變的集合,返回的是一個新建的集合,原有的集合仍是不可變的,因此只能對函數返回的集合修改。


類構造和對象

主構造器的參數聲明時加上 var 或者 val,就等價於在類中建立了該名稱的屬性
1 類默認是public final,   標識符 : 不只能夠表示繼承,還能夠表示 Java 中的 implement  基類Any

2 構造函數單獨用了一個 constructor 關鍵字來和其餘的 fun 作區分。

3 Kotlin 裏的類默認是 final 的,是不可繼承的  須要open 聲明

4 override 是有遺傳性的(若是要關閉 子類的方法寫成final override機可),open 沒有遺傳性

5 open 與 abstract關鍵字區別,abstract修飾的類沒法直接實例化,須要被繼承

6 類型判斷及強轉 is 、as、as?(可空類型使用)

7 init 代碼塊是緊跟在主構造器以後,先於次構造器執行的   
 
8 把主構造器當作身體的頭部,那麼 init 代碼塊就是頸部,次構造器就至關於身體其他部分。

9 關鍵字var val const open constructor overrider abstract Any objcet 修飾的類是單例類 ,(對象申明 對象表達)單例餓漢式的單例,而且實現了線程安全。

10 修飾符

11 kotlin實現匿名類寫法

val listener = object: ViewPager.SimpleOnPageChangeListener() {
    override fun onPageSelected(position: Int) {
        // override
    }
}   

public:公開,可見性最大,哪裏均可以引用。
private:私有,可見性最小,根據聲明位置不一樣可分爲類中可見和文件中可見。
protected:保護,至關於 private + 子類可見。
internal:內部,僅對 module 內可見。
@hide 限制客戶端訪問複製代碼

若是類中有主構造器,那麼其餘的次構造器都須要經過 this 關鍵字調用主構造器,能夠直接調用或者經過別的次構造器間接調用。若是不調用 IDE 就會報錯:
安全

class User constructor(var name: String) {
    constructor(name: String, id: Int) {
    // 👆這樣寫會報錯,Primary constructor call expected
    }
}

從主構造器的特性出發,一旦在類中聲明瞭主構造器,就包含兩點必須性:建立類的對象時,無論使用哪一個次構造器,
都須要主構造器的參與第一性:

在類的初始化過程當中,首先執行的就是主構造器若是把主構造器當作身體的頭部,那麼 init 代碼塊就是頸部,
次構造器就至關於身體其他部分。

若是在主構造器的參數聲明時加上 var 或者 val,就等價於在類中建立了該名稱的屬性(property)
而且初始值就是主構造器中該參數的值。複製代碼


常量

class Sample {
    companion object {
         👇                  // 👇
        const val CONST_NUMBER = 1
    }
}

const val CONST_SECOND_NUMBER = 2 編譯期常量 

Kotlin 的常量必須聲明在對象(包括伴生對象)或者「top-level 頂層」中,由於常量是靜態的。

Kotlin 新增了修飾常量的 const 關鍵字。

Kotlin 中只有基本類型和 String 類型能夠聲明成常量。

val 只表示只讀複製代碼

object、companion object 、top-level

juejin.im/post/5d70a2… 這裏單獨做了筆記
bash

若是寫工具類 那就直接建立一個文件 在top-level層聲明ide

若是隻是針對類,而不是針對外部使用者  就能夠寫成 companion object 或者object函數

函數

  • 本地函數(嵌套函數)

fun login(user: String, password: String, illegalStr: String) {
           👇 
    fun validate(value: String, illegalStr: String) {
      if (value.isEmpty()) {
          throw IllegalArgumentException(illegalStr)
      }
    }
   👇
    validate(user, illegalStr)
    validate(password, illegalStr)
}
這裏將共同的驗證邏輯放進了嵌套函數 validate 中,
而且 login 函數以外的其餘地方沒法訪問這個嵌套函數。複製代碼
  • 返回Unit的函數
  • 返回Nothing函數
  • 單表達式函數
  • 中綴表示法
  • 成員函數
  • 局部函數(本地函數)
  • 泛型函數
  • 內聯函數
  • 擴展函數
  • 高階函數
  • 尾遞歸函數

kotlin內置關鍵字

any

data 數據類 自動生成getset

inner 內部類申明 區別於嵌套類是能夠訪問外部類成員

object

sealed

open 

constructor

require  

inline  

suspend 掛起提醒函數  在協程與withContext配套使用  
 
tailrec 搭配尾遞歸函數,函數的最後一行是函數調用的場景,是遞歸的一種特殊情形。尾調用不必定是遞歸調用

(待增長……)

複製代碼


命名參數

fun sayHi(name: String = "world", age: Int) {
    ...
}
      👇   
sayHi(age = 21) 

在調用函數時,顯式地指定了參數 age 的名稱,這就是「命名參數」。

Kotlin 中的每個函數參數均可以做爲命名參數。
複製代碼


位置參數

1 與命名參數相對的一個概念被稱爲「位置參數」,也就是按位置順序進行參數填寫。fun sayHi(name: String = "world", age: Int, isStudent: Boolean = true, isFat: Boolean = true, isTall: Boolean = true) {
    ...
}
調用 :sayHi(name = "wo", age = 21, isStudent = false, isFat = true, isTall = false)

2 若是函數混用位置參數與命名參數,那麼全部的位置參數都應該放在第一個命名參數以前fun sayHi(name: String = "world", age: Int) {
    ...
}
sayHi(name = "wo", 21) // IDE 會報錯,Mixing named and positioned arguments is not allowed
sayHi("wo", age = 21) // 這是正確的寫法複製代碼


?. 和 ?:

val str: String? = "Hello"
                             👇
val length: Int = str?.length ?: -1
意思是若是左側表達式 str?.length 結果爲空,則返回右側的值 -1
複製代碼

Elvis 操做符還有另一種常見用法
工具

fun validate(user: User) {
    val id = user.id ?: return // 👈 驗證 user.id 是否爲空,爲空時 return 
}

// 等同於

fun validate(user: User) {
    if (user.id == null) {
        return
    }
    val id = user.id
}複製代碼


泛型通配符

定義:帶上界和下界的通配符?      與類型上界不是一個東西  T extends Object

區別:?通配符上下界 一個是能不能讀我或能不能寫我,   類型上界只是限制類型範圍

不支持協變:子類的list泛型是不能賦值給父類list的泛型,引起一個類型擦除概念因爲有類型擦除存在,保證類型
的安全,java給泛型設置了這種限制

kotlin也有以上的限制 ,由此  引起出泛型通配符,解決了限制  達到協變

java:
List<? extends TextView>   返回的類型對象 能使用get相似的     但不能set值
List<? super Button>       返回的類型對象 不能使用get一類的   但能set值 

kotlin裏面變成 :
List<out TextView> out表示 這個參數 只用來輸出,不用來輸入,只能讀我 不能寫我
List<in Button>    in 表示 這個參數 只用來輸入,不用來輸出,只能寫我,不能讀我

還能夠用在泛型的類型參數上  interface Proucer<out T> {}
泛型的繼承 在kotlin 是  <T> where T :    (一個以上繼承就須要where關鍵字)複製代碼
  • 使用關鍵字 out 來支持協變,等同於 Java 中的上界通配符 ? extends
  • 使用關鍵字 in 來支持逆變,等同於 Java 中的下界通配符 ? super

Lambda

Kotlin的lambda表達式始終用花括號包圍,花括號中經過 箭頭(->)將實參和函數體分開,
post

lambda語法結構:
性能

{x:Int, y:Int -> x+y }ui

相關文章
相關標籤/搜索