基本数据类型Int,Boolean及其他
在Java里面把基本数据类型和引用类型做了区分,例如int 和 Integer 这两个类型. 在Kotlin中不区分基本数据类型和包装类型,永远都是同一个类型(比如:Int)
val i : Int = 1
val list : List<Int> = listof(1,2,3)
不过表面上Kotlin不去区分基本数据类型和包装类型,但在编译时,kotlin是有基本数据类型和包装类型的区分的,因为用引用类型去代替基本数据类型效率是很低,所以koltin对于变量,属性,参数和返回类型都会编译成基本数据类型,唯一不可行的是泛型.
另外一点是当你在Kotlin中使用Java声明时,java基本数据类型会变成非空类型(而不是平台类型),因为它们不能持有null值.
可空的基本数据类型: Int?,Boolean?及其他
kotlin中可空类型不能用Java基本类型表示,因为null只能被存储在java的引用类型变量中。这意味着任何时候只要使用了基本数据类型的可空版本,就会编译成对应的包装类型.
下面来看一个小案例用来展示Int?的使用
data class Person(val name: String, val age: Int ?= null){
fun isOlderThan(other: Person) : Boolean?{
if(age == null || other.age == null)
return null
return age > other.age
}
}
>>>println(Person(“Sam”, 35).isOlderThan(Person(“Amy”,42)))
false
>>>println(Person(“Sam”, 35).isOlderThan(Person(“Jane”)))
null
这里必须检查两个Person的age是否都不为null. 另外如果你用基本数据类型作为泛型类的类型参数,那么Kotlin会使用该类型的包装形式. 例如下面会创建一个Interger包装类的列表,尽管你重来没有指定过可空类型或者用过null值:
val listofInts = listof(1,2,3)
数字转换
kotlin不会自动的对数字类型进行转换, 如下
val i = 1
val l : Long = i
相反,必须显示地进行转换:
val i = 1
val l : Long = I.toLong()
每一种基本数据类型(Boolean除外)都定义有转换函数: toByte(), toShort(), toChar()等。这些函数支持双向转换: 既可以把小范围的类型扩展到大范围, 比如Int.toLong(), 也可以把大范围类型截取到小范围, 比如Long.toInt().
为了避免意外情况,Kotlin要求转换必须是显示的,尤其是在比较装箱值的时候。比较两个装箱值equals方法不仅会检查它们存储的值,还要比较装箱类型。所以在Java中new Integer(42).equals(new Long(42))会返回false. 假设Kotlin支持隐式转换,你也许会这样写
val x = 1
val list = listOf(1L,2L,3L)
x in list
Kotlin要求显示地转换类型,这样只有类型相同的值才能比较:
>>> val x = 1
>>> println(x.toLong() in listOf(1L,2L,3L))
当你使用数字字面值去初始化一个类型已知的变量时,又或时把字面值作为实参传给函数时,必要的转换会自动地发生。下面代码并没有任何显式转换,但可以正确地工作:
fun foo(l : Long) = println(1)
>>> val b : Byte = 1
>>> val l = b + 1L
>>> foo(42)
“Any”和“Any?”:根类型
和Object作为Java类层级结构的根差不多,Any类型是Kotlin所有非空类型的超类型(非空类型的根)。
和Java一样,把基本数据类型的值赋给Any类型的变量时会自动装箱:
val answer : Any = 42
注意Any是非空类型,所以Any类型的变量不可以持有null值。在Kotlin中国如果你需要可以持有任何可能值的变量,包括null在内,必须使用Any?类型.
所有Kotlin类下面都包含三个方法: toString, equals和hashCode. 这些方法都继承自Any.
Unit类型: Kotlin的”void”
Kotlin中的Unit类型完成了Java中的void一样的功能。当函数没有什么有意思的结果要返回时,它可以用作函数的返回类型:
Fun f() : Unit{ … }
语法上,它和下面不带返回值的函数一样
fun f(){ … }
那么Kotlin的Unit和Java的void到底有什么不一样呢? Unit是一个完备的类型,可以作为类型参数,而void却不行。当你在重写返回泛型参数函数时这非常有用,只需要让方法返回Unit类型的值:
Interface Processor<T>{
fun process() : T
}
Class NoResultProcessor : Processor<Unit>{
override fun process(){
// do stuff
}
}
接口签名要求process函数返回一个值:而且Unit类型确实有值,所以从方法中返回它并没有问题。然而你不需要在process函数中写上显式的return语句, 因为编译器会隐式地加上return Unit.
Nothing类型:”这个函数永不返回”
对于某些Kotlin函数来说,“返回类型”的概念没有任何意义,因为它们从来不会成功地结束。例如,有些测试库有一个叫做fail的函数,它通过抛出带有特定消息的异常来让当前测试失败。
当分析调用这样函数的代码时,知道函数永远不会正常终止是很有帮助的。Kotlin使用一种特殊的返回类型Nothing来表示:
fun fail(message : String) : Nothing{
throw IllegalStateException(message)
}
>>> fail(“Error occurred”)
Java.lang.IllegalStateException : Error occurred
返回Nothing的函数可以放在Elvis运算符的右边来做先决条件检查:
val address = company.address ?: fail(“No address”)
println(address.city)
这里我们设计到了Kotlin基本数据类型,数字类型之间的转换,Unit类型还有Nothing类型.