💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## 基本数据类型 [TOC] Kotlin的数据类型和Java是大致相同的,但是他们的写法不同,并且类型之间的转换也存在着差异。而且,与java不同,**Kotlin所有数据类型都是对象,因此可在任何变量上调用成员函数和属性(字段)!Kotlin并不区分基本数据类型和它们的包装类。** 总结如下图所示 ![](https://box.kancloud.cn/68a2e6c965a8b07954cd8b63f2fb98c7_1102x749.png) 基础可参考前面章节的数据类型入门 >[info]【注意】:另外,void也可以算是一种特殊的基本类型,它也有一个装箱类 Void (跟我们后文讲到的Unit、Nothing相关)。因为,Void是不能new出来的,也就是不能在堆里面分配空间存对应的值。所以,**Void是一开始在堆栈处分配好空间**。所以,将Void归成基本类型。 ### **基本数据类型:Int、Boolean 及其他** * **Java回顾** Java 把基本数据类型和引用类型做了区分。 * 一个基本数据类型(如int)的变量直接存储了它的值, * 一个引用类型(如String )的变量存储的是指向包含该对象的内存地址的引用。 基本数据类型的值能够更高效地存储和传递,但是你不能对这些值调用方法,或是把它们存放在集合中。Java 提供了特殊的包装类型(比如`java.lang.Integer` ),**在你需要对象的时候对基本数据类型进行封装**。因此,你不能用`Collection<int>`来定义一个整数的集合,而必须用`Collection<Integer>`来定义。 * **kotln中的数据类型** Kotlin并不区分基本数据类型和包装类型,你使用的永远是同一个类型(比如:Int) ``` val i: Int = 1 val list: List<Int > = listOf(l, 2, 3) ``` 还能对一个数字类型的值调用方法。例如下面这段代码中, 使用了标准库的函数coerceIn 来把值限制在特定范围内: ~~~ fun main(args: Array<String>) { showProgress(146) } fun showProgress(progress:Int){ val percent =progress.coerceIn(0,100) println("We're ${percent}% done!") } ~~~ 运行结果 ``` We're 100% done! Process finished with exit code 0 ``` >[info]【注意】如果基本数据类型和引用类型是一样的,但并不意味着Kotlin使用对象来表示所有的数字,很低效,所以Kotlin 并没有这样做。 在运行时,数字类型会尽可能地使用最高效的方式来表示。大多数情况下一一对于变量、属性、参数和返回类型——Kotlin 的Int 类型会被编译成Java 基本数据类型int 。唯一不可行的例外是泛型类,比如集合。用作泛型类型参数的基本数据类型会被编译成对应的Java 包装类型。例如, Int 类型被用作集合类的类型参数时,集合类将会保存对应包装类型`java.lang.Integer` 的实例。 像Int 这样的Kotlin 类型在底层可以轻易地编译成对应的Java 基本数据类型,因为两种类型都不能存储null 引用。反过来也差不多: **当你在Kotlin 中使用Java声明时,Java 基本数据类型会变成非空类型(而不是平台类型),因为它们不能持有null 值**。 ### **可空的基本数据类型:Int?、Boolean?及其他** Kotlin 中的可空类型不能用Java 的基本数据类型表示,因为null只能被存储在Java的引用类型的变量中。这意味着任何时候只要使用了基本数据类型的可空版本,它就会编译成对应的包装类型。 **使用可空的基本数据类型** ``` fun main(args: Array<String>) { println(Man("Sam",35).isOlderThan(Man("Amy",42))) println(Man("Sam",35).isOlderThan(Man("Amy"))) } class Man(val name:String,val age:Int?=null){ fun isOlderThan(other:Man):Boolean?{ if(age ==null ||other.age ==null) return null return age > other.age } } ``` 运行结果 ``` false null Process finished with exit code 0 ``` 【注意】普通的可空性规则如何在这里应用?你不能就这样比较Int?类型的两个值,因为它们之中任何一个都可能为null 。相反,你必须检查两个值都不为null 。然后,编译器才允许你正常地比较它们。 在Man类中声明的age 属性的值被当作`java.lang.Integer` 存储。但是只有在你使用来自Java 的类时这些细节才有意义。为了在Kotlin 中选出正确的类型,你只需要考虑对变量或者属性来说,null是否是它们可能的值。 泛型类是包装类型应用的另一种情况。如果你用基本数据类型作为泛型类的类型参数,那么Kot lin 会使用该类型的包装形式。例如,下面这段代码创建了一个Integer 包装类的列表,尽管你从来没有指定过可空类型或者用过null 值: ``` val listOfInts = listOf(1,2,3) ``` 这是由Java 虚拟机实现泛型的方式决定的。**JVM不支持用基本数据类型作为类型参数,所以泛型类(Java 和Kotlin 一样)必须始终使用类型的包装表示**。因此,假如你要高效地存储基本数据类型元素的大型集合,要么使用支持这种集合的第三方库(如Trove4J, http: //trove.starlight-systems.com),要么使用数组来存储。本章末尾我们会讨论数组的细节。