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 }