Kotlin代数数据类型、模式匹配、泛型相关(学习笔记三)

三、代数数据类型和模式匹配

其实都是些设计思想,我们在开发中都用到了,需要在开发中不断积累领悟。

1、代数数据类型概念理解

代数就是能代表数字的字母或符号

这种用代数或者数字转换成的类型,以及通过这些类型所产生的的新的类型就叫做代数数据类型,有点绕口哈哈。

其实我们用的枚举就是代数数据类型的一种,后边我们会慢慢体会到它带来的好处。

2、何为模式?模式即为表达式,常见模式有常量模式、类型模式、逻辑表达式模式

常量模式就是比较两个常量是否相等,比如if elseswitch case

类型模式类似于java的 instanceOf circle instanceOf Shape kotlin的 is Shape 类型检查

逻辑表达式模式可以理解为 if elseswitch case实现起来比较麻烦(比如在if条件里做比较多的逻辑判断等),用逻辑表达式模式实现起来比较简洁的模式,

3、何为模式匹配?模式匹配中的模式即为表达式,匹配的也是表达式,模式匹配的核心就是解构(反向构造表达式),如下结构:
when(expre){
    expre1->{}
    expre2->{}
}

四、类型系统

1、java NPE(空指针)

解决方案:

抛异常处理

采用注解@NotNull @Nullable

用Optional对象对可空的数据进行装箱,这类Optional对象必须拆箱后才能参与运算,因而拆箱的步骤就提醒使用者必须处理null的情况。但是这种情况在大数据量的情况下会导致损耗性能和时间的增加

2、kotlin的可空类型

安全调用:a?.b?.c 只有a或者b不为空的情况下才会继续往下调用

Elvis操作符(合并运算符):java写法 string a = b==null?c:b.e; kotlin大法 var a = b?c:.e

非空断言:!! a!!.b 当a为空时就会抛出NPE

智能类型转换,因为kolin是会进行类型自动推导的,所以他没有java的强转,为了语义或者阅读方便我们一般用 as或者as?来标记变量的类型,as?会防止变量为空触发空引用。

类型转换的封装 inline fun <reified T> cast(original: Any) : T? = original as? T

使用 var a = cast<String>

3 、面向对象设计

  1. Any是所有非空类型的超类,Any?是所有类型的超类 Any相当于java的 Object

  2. 自动装箱,基本类型转为包装类,自动拆箱是包装类转为基本类型

  3. Kotlin中一切皆对象,Int等价于java的int Int?等价于java的Integer

  4. 新数组 Array 、IntArray(int[])、CharArray(char[])、ShortArray(short[])

  5. val a = arrayOf(1,2,3);

    val a = intArrayOf(1,2,3);

    IntArray 并不是Array的子类

4、泛型

1、 泛型类 class Animal<T> {} 

2、泛型接口 interface IAnimal < T > {}  

3、泛型方法 fun < T > initAnimal (param : T) {}

4、泛型约束, 表示我们可以指定泛型类型(T)的上界,即父类型,默认的上界为 Any? ,如果只有一个上界可以这样指定:

fun <T : Animal<T>> initAnimal(param: T) {}

即Animal<T>就是上界类型,这里使用了:,在 Java 中对应extends关键字,如果需要指定多个上界类型,就需要使用where语句:

fun <T> initAnimal(param: T) where T : Animal<T>, T : IAnimal<T> {}

5、协变和逆变

Kotlin 中的泛型是默认不型变的

in代表泛型参数类型逆变,逆变泛型类型的父类型是被保留的,它只能出现在函数的输入位置,作为参数。

out代表泛型参数类型协变,协变泛型类型的子类型是被保留的。

消费者 in, 生产者 out,统称为型变。

使用 out 使得一个类型参数协变,协变类型参数只能用作输出,可以作为返回值类型但是无法作为入参的类型,而in则刚好相反。

比较:

Kotlin 中的out A类似于 Java 中的? extends A,即泛型参数类型必须是A或者A的子类,用来确定类型的上限

Kotlin 中的in A类似于 Java 中的? super A,即泛型参数类型必须是B或者B的父类,用来确定类型的下限

6、 于星号投射,其实就是*代指了所有类型,相当于Any? 我们不知道泛型参数的类型信息时,但仍需要安全的使用它时,可以使用星投影,用星号 * 表示,星投影和 Java 中的原始类型很像,但星投影是安全

示例:

class A<T>(val t: T, val t2 : T, val t3 : T)

class Apple(var name : String)

fun main(args: Array<String>) {

//使用类

val a1: A<*> = A(12, "String", Apple("苹果"))

val a2: A<Any?> = A(12, "String", Apple("苹果")) //和a1是一样的

val apple = a1.t3 //参数类型为Any

println(apple)

val apple2 = apple as Apple //强转成Apple类

println(apple2.name)

//使用数组

val l:ArrayList<*> = arrayListOf("String",1,1.2f,Apple("苹果"))

for (item in l){

println(item)

}

}

更多学习

kotlin基础语法(学习笔记一)
kotlin面向对象(学习笔记二)

关注我获取更多知识或者投稿

我来评几句
登录后评论

已发表评论数()

相关站点

热门文章