學(xué)習(xí)需要一步步進(jìn)行,前面已學(xué)習(xí)過(guò)了部分kotlin基礎(chǔ)語(yǔ)法<Kotlin基礎(chǔ)語(yǔ)法一>
?;A(chǔ)語(yǔ)法的學(xué)習(xí)與總結(jié)會(huì)讓我對(duì)知識(shí)了了解更加深入,也算是對(duì)自己的激勵(lì)吧。
Kotlin-數(shù)組
- 數(shù)組在kotlin中的使用Array<T>類(lèi)來(lái)表示
- 基本類(lèi)型數(shù)組:ByteArray,LongArray,xxxArray等,這些類(lèi)是基本類(lèi)型數(shù)組,但是跟Array類(lèi)沒(méi)有繼承關(guān)系
- 數(shù)組的創(chuàng)建
- 使用arrayOf()函數(shù)(java的靜態(tài)初始化)
- 使用arrayOfNulls()函數(shù)(java的動(dòng)態(tài)初始化)
- 使用emptyArray()函數(shù)
- 使用Array(size:Int,init:(int)->T)構(gòu)造器
fun main(){
val arr = intArrayOf(1,2,20,36,45,8)
for((index,value) in arr:withIndex()){
println("索引為${index}的元素是:${value}")
}
}
Kotlin的集合
| java中的類(lèi)型 | Kotlin中的只讀類(lèi)型 | Kotlin中的可變類(lèi)型 |
|---|---|---|
| Iterator<T> | Iterator<T> | MutableIterator<T> |
| Iterable<T> | Iterable<T> | MutableIterable<T> |
| Collection<T> | Collection<T> | MutableCollection<T> |
| Set<T> | Set<t> | MutableSet<t> |
| List<T> | List<T> | MutableList<T> |
| ListIterator<T> | ListIterator<T> | MutableListIterator<T> |
| Map<K,V> | Map<K,V> | MutableMap<K,V> |
| Map.Enrty<K,V> | Map.Entry<K,V> | MutableMap.MutableEntry<K,V> |
- kotlin集合可分為可變和不可變集合
- 聲明并初始化List的集合,使用listOf(..)函數(shù)
- 聲明并初始化MutableList的集合,使用mutableListOf(..)函數(shù)/listOfNotNull()/arrayListOf()
- 聲明并初始化Set集合,使用setOf(..)函數(shù)
- 聲明并初始化MutableSet的集合,使用mutableSetOf(..)函數(shù)/hashSetOf()/linkedSetOf()/sortedSetOf()
- 不可變的Map類(lèi)型的初始化,使用mapOf()函數(shù)
- 可變的Map類(lèi)型集合的初始化,使用mutableMapOf()函數(shù)/hashMapOf()/linkedMapOf()/sortedMapOf()
for循環(huán)使用
fun main() {
val items = listOf("java", "kotlin", "android")
for (item in items) {
println(item)
}
}
fun main() {
val items = listOf("java", "kotlin", "android")
for (index in items.indices) {
println("item at $index is ${items[index]}")
}
}
Kotlin的泛型
先了解一下java的泛型
上界通配符 < ? extends X>。用 extends 關(guān)鍵字聲明,表示參數(shù)化的類(lèi)型可能是所指定的類(lèi)型,或者是此類(lèi)型的子類(lèi)。
上界 ->取出來(lái)的類(lèi)型不會(huì)丟失,存放會(huì)丟失類(lèi)型。(?代表容器里的元素類(lèi)型為X基類(lèi)類(lèi)型,X是所有元素的基類(lèi),存(即set)進(jìn)去就無(wú)法確定是那個(gè)具體的類(lèi)型了,取出來(lái)就沒(méi)有問(wèn)題,因?yàn)閄是表示所有基類(lèi))
下界通配符 < ? super E>。用 super 進(jìn)行聲明,表示參數(shù)化的類(lèi)型可能是所指定的類(lèi)型,或者是此類(lèi)型的父類(lèi)型,直至 Object。
下界 ->取出來(lái)的類(lèi)型會(huì)丟失,存放不會(huì)丟失類(lèi)型。(?代表容器里的元素類(lèi)型為E基類(lèi)類(lèi)型,存(即set)進(jìn)去的都是E的超類(lèi),取出來(lái)就不知道是那個(gè)具體的類(lèi)型,這樣就沒(méi)法統(tǒng)一基類(lèi)類(lèi)型了,全部都為Object)
上界、下界遵循PECS (Producter Extends Consumer Super)
Producter 產(chǎn)生者 -> 取
Consumer 消費(fèi)者 -> 存
Kotlin的泛型 jvm泛型從java中繼續(xù)過(guò)來(lái)的
out(相當(dāng)于java的上界)取出來(lái)是沒(méi)有問(wèn)題,存進(jìn)去就有問(wèn)題。 out在Kotlin中叫協(xié)變。
in(相當(dāng)于java的下界)存進(jìn)去沒(méi)有問(wèn)題,取出來(lái)就是問(wèn)題。 in在Kotlin中叫逆變。
有一個(gè)copy數(shù)組的函數(shù),看如下代碼:
fun copy(destArr:Array<Double>,srcArr:Array<Double>){
}
fun main(){
var destDouble = arrayOf<Double>()
var srcDouble = arrayOf<Double>(1.1,2.2,3.3)
copy(destDouble,srcDouble)
}
如果有多種類(lèi)型的數(shù)組要copy,那么copy函數(shù)就得復(fù)寫(xiě)多個(gè)。復(fù)寫(xiě)多個(gè)copy函數(shù),這樣寫(xiě)代碼臃腫,也不優(yōu)雅??聪旅娲a如何優(yōu)雅實(shí)現(xiàn)根據(jù)不同類(lèi)型實(shí)現(xiàn)copy函數(shù)。
//泛型函數(shù) 泛型
fun <T> copy(destArr:Array<T>,srcArr:Array<T>){
}
fun main(){
var destDouble = arrayOf<Double>()
var srcDouble = arrayOf<Double>(1.1,2.2,3.3)
copy(destDouble,srcDouble)
var destInt = arrayOf<Int>()
var srcInt = arrayOf(1,2,3)
copy(destInt,srcInt)
}
不錯(cuò)上述的copy函數(shù)就是使用了泛型,也是一個(gè)簡(jiǎn)單的使用。copy這個(gè)泛型函數(shù),還是存在問(wèn)題的,Int/Double的父類(lèi)為Number。如果destArrc參數(shù)傳入一個(gè)arrayOf<Number>數(shù)組,那么copy函數(shù)就報(bào)錯(cuò)了。這個(gè)問(wèn)題也很容易解決,把srcArr存放到destArr數(shù)組中,那么把destArr的泛型改為逆變就可以了(destArr:Array<in T>)。如下代碼:
fun <T> copy(dest:Array<in T>,src:Array<T>){
//把srcArr的內(nèi)容拿出來(lái),存放到destArr數(shù)組中
srcArr.forEachIndexed{ index,value->destArr[index] = srcArr[index]}
}
fun main(){
var srcInt = arrayOf(1,2,3)
var destNum = arrayOf<Number>(3)
copy(destNum,srcInt)
}
上述的dest:Array<in T>,in T ( 相當(dāng)于java中的 ?super T)是一個(gè)逆變。逆變之后,可以把Array<Number>理解為Array<Int>/Array<Double>的子類(lèi)。上面的copy泛型函數(shù)寫(xiě)法還寫(xiě)成另一種,代碼如下:
fun <T> copy(dest:Array<T>,src:Array<out T>){
//把srcArr的內(nèi)容拿出來(lái),存放到destArr數(shù)組中
srcArr.forEachIndexed{ index,value->destArr[index] = srcArr[index]}
}
fun main(){
var srcInt = arrayOf(1,2,3)
var destNum = arrayOf<Number>(3)
copy(destNum,srcInt)
}
copy(dest:Array<T>,src:Array<out T>)是協(xié)變的寫(xiě)法。src:Array<out T>取出來(lái)的類(lèi)型一定是T類(lèi)型,所以存放到destArr<T>是沒(méi)有問(wèn)題的。
特別例子:在java不允許泛型使用方式,而在kotlin中可以使用
java中不允許泛型使用的方式,代碼如下:
public class A{
interface Callback<T>{//聲明處形變
T getT();
}
interface Call<? extends K>{//聲明處形變 是不允許這樣使用的 無(wú)法聲明處形變的
}
void test(Callback<String> callback){
Callback<String> cb = callback;//java 是不允許這樣使用的
}
}
kotlin中可以使用java中不允許泛型使用的方式,代碼如下:
interface Callback<out T>{
fun getT():T
}
fun test(src:Callback<String>){
val dest:Callback<Any?> = src
}
從上述兩處代碼得出:kotlin對(duì)java的泛型的增強(qiáng),多了一個(gè)聲明處形變。
Kotlin的lambda
{ }就是表示一個(gè)lambda表達(dá)式
fun main(){
var sum ={x:Int,y:Int -> x+y}
//lambda表達(dá)式調(diào)用
com.lu.kotlindemo.testFun.sum(1,3)
}
fun main(){
var temp:(Int,Int)->Int //相當(dāng)于 var temp:Any
//這是一個(gè)lambda { }
temp ={x:Int,y:Int -> x+y}
val sum = temp.invoke(2,2)
println("相加:${sum}")
temp ={x:Int,y:Int -> x*y}
val c = temp.invoke(3,4)
println("相乘:${c}")
//這也是一個(gè)lambda
var tmp :(Int)->Unit
tmp ={ println("$it")}//這個(gè)it代表只有一個(gè)參數(shù)(默認(rèn)只有一個(gè)參數(shù))
}
var temp:(Int,Int)->Int 。聲明處用括號(hào)括起來(lái),也是就是定義一個(gè)類(lèi)型 ,傳入兩個(gè)Int類(lèi)型參數(shù)并返回一個(gè)Int類(lèi)型值。相當(dāng)于 var temp:Any。
tmp ={ println("$it")},注意:這個(gè)it代表只有一個(gè)參數(shù)(默認(rèn)只有一個(gè)參數(shù))。如果有返回值,最后一句就是代表返回值,不能要{}里面return。
錯(cuò)誤代碼:
tmp ={
println("$it")
return //不能夠這樣寫(xiě)return
}
正確代碼:
tmp ={
println("$it")
it+3 //最后一句 代表返回值
}