Kotlin基础语法<二>

学习需要一步步进行,前面已学习过了部分kotlin基础语法
。基础语法的学习与总结会让我对知识了了解更加深入,也算是对自己的激励吧。

Kotlin-数组

  1. 数组在kotlin中的使用Array类来表示
  2. 基本类型数组:ByteArray,LongArray,xxxArray等,这些类是基本类型数组,但是跟Array类没有继承关系
  3. 数组的创建
    • 使用arrayOf()函数(java的静态初始化)
    • 使用arrayOfNulls()函数(java的动态初始化)
    • 使用emptyArray()函数
    • 使用Array(size:Int,init:(int)->T)构造器
fun main(){
    val arr = intArrayOf(1,2,20,36,45,8)
    for((index,value) in arr:withIndex()){
        println("索引为${index}的元素是:${value}")
    }
}

Kotlin的集合

java中的类型 Kotlin中的只读类型 Kotlin中的可变类型
Iterator Iterator MutableIterator
Iterable Iterable MutableIterable
Collection Collection MutableCollection
Set Set MutableSet
List List MutableList
ListIterator ListIterator MutableListIterator
Map Map MutableMap
Map.Enrty Map.Entry MutableMap.MutableEntry
  1. kotlin集合可分为可变和不可变集合
  2. 声明并初始化List的集合,使用listOf(..)函数
  3. 声明并初始化MutableList的集合,使用mutableListOf(..)函数/listOfNotNull()/arrayListOf()
  4. 声明并初始化Set集合,使用setOf(..)函数
  5. 声明并初始化MutableSet的集合,使用mutableSetOf(..)函数/hashSetOf()/linkedSetOf()/sortedSetOf()
  6. 不可变的Map类型的初始化,使用mapOf()函数
  7. 可变的Map类型集合的初始化,使用mutableMapOf()函数/hashMapOf()/linkedMapOf()/sortedMapOf()

for循环使用

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 关键字声明,表示参数化的类型可能是所指定的类型,或者是此类型的子类。

上界 ->取出来的类型不会丢失,存放会丢失类型。(?代表容器里的元素类型为X基类类型,X是所有元素的基类,存(即set)进去就无法确定是那个具体的类型了,取出来就没有问题,因为X是表示所有基类)

下界通配符 < ? super E>。用 super 进行声明,表示参数化的类型可能是所指定的类型,或者是此类型的父类型,直至 Object。

下界 ->取出来的类型会丢失,存放不会丢失类型。(?代表容器里的元素类型为E基类类型,存(即set)进去的都是E的超类,取出来就不知道是那个具体的类型,这样就没法统一基类类型了,全部都为Object)

上界、下界遵循PECS (Producter Extends Consumer Super)

Producter 产生者 -> 取
Consumer 消费者 -> 存

详细的java泛型

Kotlin的泛型 jvm泛型从java中继续过来的

out(相当于java的上界)取出来是没有问题,存进去就有问题。 out在Kotlin中叫协变。

in(相当于java的下界)存进去没有问题,取出来就是问题。 in在Kotlin中叫逆变。

有一个copy数组的函数,看如下代码:

fun copy(destArr:Array,srcArr:Array){
}

fun main(){
    var destDouble = arrayOf()
    var srcDouble = arrayOf(1.1,2.2,3.3)
    copy(destDouble,srcDouble)
}

如果有多种类型的数组要copy,那么copy函数就得复写多个。复写多个copy函数,这样写代码臃肿,也不优雅。看下面代码如何优雅实现根据不同类型实现copy函数。

//泛型函数   泛型
fun  copy(destArr:Array,srcArr:Array){
}

fun main(){
    var destDouble = arrayOf()
    var srcDouble = arrayOf(1.1,2.2,3.3)
    copy(destDouble,srcDouble)

    var destInt = arrayOf()
    var srcInt = arrayOf(1,2,3)
    copy(destInt,srcInt)
}

不错上述的copy函数就是使用了泛型,也是一个简单的使用。copy这个泛型函数,还是存在问题的,Int/Double的父类为Number。如果destArrc参数传入一个arrayOf数组,那么copy函数就报错了。这个问题也很容易解决,把srcArr存放到destArr数组中,那么把destArr的泛型改为逆变就可以了(destArr:Array)。如下代码:

fun  copy(dest:Array,src:Array){
    //把srcArr的内容拿出来,存放到destArr数组中
    srcArr.forEachIndexed{ index,value->destArr[index] = srcArr[index]}
}
fun main(){
    var srcInt = arrayOf(1,2,3)
    var destNum = arrayOf(3)
    copy(destNum,srcInt)
}

上述的dest:Array,in T ( 相当于java中的 ?super T)是一个逆变。逆变之后,可以把Array理解为Array/Array的子类。上面的copy泛型函数写法还写成另一种,代码如下:

fun  copy(dest:Array,src:Array){
    //把srcArr的内容拿出来,存放到destArr数组中
    srcArr.forEachIndexed{ index,value->destArr[index] = srcArr[index]}
}

fun main(){
    var srcInt = arrayOf(1,2,3)
    var destNum = arrayOf(3)
    copy(destNum,srcInt)
}

copy(dest:Array,src:Array)是协变的写法。src:Array取出来的类型一定是T类型,所以存放到destArr是没有问题的。

特别例子:在java不允许泛型使用方式,而在kotlin中可以使用

java中不允许泛型使用的方式,代码如下:

public class A{
    interface Callback{//声明处形变 
        T getT();
    }
    interface Call{//声明处形变 是不允许这样使用的  无法声明处形变的 
    }
    void test(Callback callback){
        Callback cb = callback;//java 是不允许这样使用的
    }
}

kotlin中可以使用java中不允许泛型使用的方式,代码如下:

interface Callback{
    fun getT():T
}

fun test(src:Callback){
    val dest:Callback = src
}

从上述两处代码得出:kotlin对java的泛型的增强,多了一个声明处形变。

Kotlin的lambda

{ }就是表示一个lambda表达式

fun main(){
    var sum ={x:Int,y:Int -> x+y}
    //lambda表达式调用
    com.lu.kotlindemo.testFun.sum(1,3) 
}
fun main(){
    var temp:(Int,Int)->Int  //相当于 var temp:Any
    //这是一个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}")

    //这也是一个lambda
    var tmp :(Int)->Unit 
    tmp ={ println("$it")}//这个it代表只有一个参数(默认只有一个参数)
}

var temp:(Int,Int)->Int 。声明处用括号括起来,也是就是定义一个类型 ,传入两个Int类型参数并返回一个Int类型值。相当于 var temp:Any。

tmp ={ println("$it")},注意:这个it代表只有一个参数(默认只有一个参数)。如果有返回值,最后一句就是代表返回值,不能要{}里面return。

错误代码:

tmp ={
    println("$it")
    return //不能够这样写return
}

正确代码:

tmp ={
    println("$it")
    it+3 //最后一句 代表返回值
}

你可能感兴趣的:(Kotlin基础语法<二>)