Kotlin从入门到精通 | 第三章 Kotlin内置类型
本章节主要介绍Kotlin的内置类型和简单用法
变量的声明
1 | val b: String = "Hello Kotlin" |
Kotlin的变量声明方式,有点类似于TypeScript
,是比较现代的一种做法,一般形式为修饰符 变量名: 类型 = 值
,其中,类型声明可以省略。
修饰符有两种
- val:只读变量
- var:可读写变量,定义时必须指定值,且不可更改
与Java对比
1 | int a = 2; |
1 | var a = 2 |
易混淆的Long类型标记
在Java里,Long
类型结束使用l
是可以编译通过,只是不推荐(小写的l
,看起来就跟数字1一样)
1 | long c = 1234567890l; // ok but not good. |
在Kotlin里面,直接就编译不通过,强制要求修改为L
1 | val c = 1234567890l // compile error. |
Kotlin数值类型转换
在Java里,int
类型可以隐式转换为long
1 | int e = 10; |
而到了Kotlin这,对不起,不支持
1 | val e: Int = 10 |
无符号类型(兼容C Native)
从v1.3开始,Kotlin支持无符号类型
字符串定义
先看下Kotlin定义HTML字符串的代码
1 | val n = """ |
对比Java,简直太简洁了,使用Java定义的一段同样行为的代码,一堆换行符,看了都头大
Kotlin字符串
字符串比较
a == b
:比较内容,等价于Java的equals
a === b
:比较对象是否是同一个对象
字符串模板
- “hello, $name” => “Hello, 小明”
数组
Kotlin | Java | |
---|---|---|
整型 | IntArray | int[] |
整型装箱 | Array |
Integer[] |
字符 | CharArray | char[] |
字符装箱 | Array |
Character[] |
字符串 | Array |
String[] |
数组的创建
1 | int[] c = new int[]{1, 2, 3, 4, 5}; |
在Kotlin里面,数组使用以下方式创建
1 | val c0 = intArrayOf(1, 2, 3, 4, 5) |
数组的长度
Java
1 | int[] a = new int[5]; |
Kotlin
1 | val a = IntArray(5) |
数组的读写
Java
1 | String[] d = new String[]{"Hello", "World"}; |
Kotlin
1 | val d = arrayOf("Hello", "World") |
数组的遍历
Java
1 | float[] e = new float[]{1, 3, 5, 7}; |
Kotlin,有点像Python里面的元素遍历了
1 | val e = floatArrayOf(1f, 3f, 5f, 7f) |
或者还可以使用forEach
高阶函数
1 | e.forEach { element -> println(element) } |
数组的包含关系
Java
1 | for(float element : e) { |
而在Kotlin里面,简单的不行
1 | if(1f in e) { |
区间
这个Java里是没有,所以只看Kotlin的写法
区间的创建
闭区间(..)
1 | val intRange = 1..10 // [1,10] |
开闭区间,前闭后开(until)
1 | val intRangeExclusive = 1 until 10 // [1,10) |
倒序区间(downTo)
1 | val intRangeReverse = 10 downTo 1 // [10,9,...,1] |
区间的步长(step)
在定义区间时,我们还可以定义步长,默认步长为1
1 | val intRangeWithStep = 1..10 step 2 // [1, 3, 5, 7, 9] |
区间的迭代
区间的迭代跟数组基本是类似的
1 | for(element in intRange) { |
区间的包含关系
1 | if(3 in intRange) { |
区间的应用
1 | val array = intArrayOf(1, 3, 5, 7) |
其中,array.indices
返回的就是数组索引范围的区间
集合框架
Kotlin在Java集合的基础上,做出了一些增强,具体表现为以下几点
- 增加了“不可变”集合框架的接口
- 没有另起炉灶,复用Java Api的所有实现类型
- 提供了丰富医用的方法,例如
forEach/map/flatMap
等
Scala也是一门JVM语言,Kotlin很多特性都参考了Scala
集合框架的接口类型对比
Kotlin | Java | |
---|---|---|
不可变List | List |
List |
可变List | MutableList |
List |
不可变Map | Map<K, V> | Map<K, V> |
可变Map | MutableMap<K, V> | Map<K, V> |
不可变Set | Set |
Set |
可变Set | MutableSet |
Set |
集合框架的创建
Java
1 | List<Integer> intList = new ArrayList<>(Arrays.asList(1, 2, 3)); |
Kotlin
1 | val intList: List<Int> = listOf(1, 2, 3) // 不能添加或者删除元素 |
集合实现类复用与类型别名
我们来比较一下Java与Kotlin创建集合的代码
Java
1 | List<String> stringList = new ArrayList<>(); // java.util.ArrayList |
Kotlin
1 | val stringList = ArrayList<String>() // kotlin.collections.ArrayList |
Kotlin里面集合的类型别名定义
1 | public actual typealias ArrayList<E> = java.util.ArrayList<E> |
Kotlin使用类型别名,是出于跨平台的考虑,同一份代码,Kotlin不只是希望能跑在JVM平台,也可以是Native平台,所以,说不定有朝一日,Kotlin编译出来的不再是Java字节码,而是二进制机器码!
集合框架的读写
Kotlin还支持运算符重载
添加元素
Java
1 | for(int i = 0; i < 10; i++) { |
Kotlin
1 | for(i in 0..10) { |
删除元素
Java
1 | for(int i = 0; i < 10; i++) { |
Kotlin
1 | for(i in 0..10) { |
修改元素
Java
1 | stringList.set(5, "HelloWorld"); |
Kotlin
1 | stringList[5] = "HelloWorld" |
如果是Map
Java
1 | HashMap<String, Integer> map = new HashMap<>(); |
Kotlin
1 | val map = HashMap<String, Int>() |
几个重要的数据结构
Pair
可以理解为键值对,包含first
和second
两个字段的数据结构
1 | val pair = "Hello" to "Kotlin" |
Triple
跟Pair
类似,不过含有三个值
1 | val triple = Triple("x", 2, 3.0) |
函数
在Kotlin里面,函数也是类型的一种,是一等公民,可以赋值、传递,并在合适的条件下调用
学习路线图
函数的定义
一个函数包含:函数名,函数参数列表,函数返回值,函数体
1 | fun main(args: Array<String>):Unit { |
函数 VS 方法
- 方法可以认为是函数的一种特殊类型
- 从形式上,有
receiver
的函数即为方法
函数的类型
在Kotlin里,函数也是有类型的
1 | fun foo() { } // () -> Unit |
函数的引用
函数的引用类似于C语言中的函数指针,可用于函数传递
1 | fun foo() { } // val f: () -> Unit = ::foo |
绑定receiver的函数引用
1 | val foo = Foo() |
变长参数(vararg关键字)
1 | fun main(vararg args: String) { |
多返回值
Pair或Triple定义返回值,使用结构获取返回值
1 | fun multiReturnValues(): Triple<Int, Long, Double> { |
默认参数
Kotlin允许为参数指定默认值,这样一来,就不必像Java一样定义方法重载了
1 | fun defaultParameter(x: Int, y: String, z: Long = 0L) { |
具名函数
1 | fun defaultParameter(x: Int = 5, y: String, z: Long = 0L) { // 不是最后的参数 |