Kotlin基础(五)Kotlin的类型系统

时间:2022-01-24 14:19:12

Kotlin的类型系统

 一、可空类型

 1 //s为null的话编译器会报错,没问号不能为空
 2 fun strLen(s : String)=s.length
 3 //如果允许s为空可:
 4 fun strLen2(s : String?) : Int{
 5     if (s!=null) return s.length
 6     else return 0
 7 }
 8 /*
 9 注意可空类型和不可空类型只是在编译期做的
10 检查不同,runtime这两者并无区别
11 */
12 
13 
14 //"?."的用法
15 fun strLen3(s : String?) :Int?=s?.length
16 //相当于
17 fun strLen4(s : String?) :Int?{
18     //如果是为null则返回null,不为null就返回"."后面的调用结果
19     if (s!=null) return s.length
20     else return null
21 }
22 
23 //"?:"的用法
24 fun foo(s: String?){
25     //如果为null,则s="",s不为null其值为自身不变
26     val t: String=s ?: ""
27 }
28 //结合使用
29 fun strLenSafe(s: String?) :Int=s?.length?:0
30 
31 //"as?"的用法:尝试将一个值转换为指定类型,转换不成功则返回null
32 class Person(val firstName: String, val lastName: String) {
33     override fun equals(o: Any?): Boolean {
34         val otherPerson = o as? Person ?: return false
35         return otherPerson.firstName == firstName &&
36                 otherPerson.lastName == lastName
37     }
38     override fun hashCode(): Int =
39             firstName.hashCode() * 37 + lastName.hashCode()
40 }
41 
42 //非空判断"!!"用法
43 fun ignoreNulls(s:String?) {
44     val sNotNull: String=s!!
45     //do sth
46 }

 

 1 /**
 2 * let函数:把一个调用它的对象变换为lambda表达式的参数
 3 * */
 4 
 5 fun sendEmail(address: String)= println("Send an email to $address")
 6 
 7 fun main(args: Array<String>) {
 8     //复杂的做法
 9     val address: String?="tang@163.com"
10     if (address!=null) sendEmail(address)
11     //使用let函数简化代码
12     address?.let(::sendEmail)
13 }
1 class Girle {
2     //lateinit修饰符,延迟初始化,但不能延迟基础类型
3     private lateinit var age : Secrit
4 }
5 
6 class Secrit

类型参数的可空性:在Kotlin中所有泛型类和泛型函数的类型参数默认都是可空的,要使类型参数非空,必须为它指定一个非空的上界。

fun <T: Any> printHashCode(t: T){
    println(t.hashCode())
}

二、基本数据类型和其他基本类型

1.Kotlin表面上并不区分基本类型和其包装类型,但实际上基本类型,如数字类型尽可能地被高效地使用

所以大多数情况下它们会被编译为基本类型,唯一不可行的是泛型类。

2.在Kotlin中使用Java时,Java的基本类型一定会被编译为非空类型,而不是平台类型。

3.任何时候只要使用了基本类型的可空版本,它们就会变为包装类型。

4.Any:所有非空类型(包括基本类型)的超类。把基本数据类型赋值给Any时会自动装箱。Any只能使用Java中equals,toString,hashCode方法,其他方法并不能使用。

5.Unit:Kotlin中的“void”

 1 interface Pro<T>{
 2     fun p() : T
 3 }
 4 
 5 /*
 6 * 与Java中的void不同的是Unit是一个完备的类型
 7 * 可以作为类型参数,而void却不行。
 8 * */
 9 class NoResultPro : Pro<Unit>{
10     //当使用泛型时,Unit表示没有值
11     override fun p() {
12         //do sth
13     }
14 }

6.Nothing类型:表示这个函数永远不会返回。

1 fun fail(msg: String): Nothing{
2     throw IllegalStateException(msg)
3 }

三、集合与数组

1.可空性和集合:Kotlin完全支持类型参数的可空性。

2.只读集合和可变集合:Kotlin的集合设计和Java不同的是,把访问集合数据的接口和修改集合的数据接口分开了。

但要注意:只读集合并不是不变的,并不是线程安全的。因为,只读集合可能只是同一个集合众多引用中的一个。

fun <T> copyEle(source: Collection<T>,target: MutableCollection<T>){
    for (item in source) target.add(item)
}

3.Kotlin集合和Java集合:可变接口直接对应Java中的集合接口,只读版本缺少了所有产生改变的方法。

4.作为平台类型的集合:向Java方法传递可读集合没有用(Java可以修改它)

5.Kotlin中的一个数组是一个带有类型参数的类,创建数组的方法:

1 fun main(args: Array<String>) {
2     //arryof创建数组
3     val ar=arrayOf("one","tow","three","four")
4     //arryOfNulls创建一个给定大小的数组,包含的是null元素
5     val s = arrayOfNulls<String?>(8)
6     //Array构造方法接收数组的大小和一个lambda表达式(用来创建每一个元素)
7     Array<String>(22) {m -> ("b"+m)}
8 }

基本类型数组:

1 fun main(args: Array<String>) {
2     val s=IntArray(3)
3     val m= intArrayOf(1,2,3,4)
4     val h=IntArray(5){i -> i*8}
5 }