自从google宣布kotlin成为android开发一级语言,国内就掀起了一股学习热潮,kotlin有以下优点:
- 简洁易读
- 没有分号
- 字符串模板
- 空安全
- 自带数据类支持
- 支持函数属性扩展和代理
- 兼容java
- 智能类型转换
- 类型推断
- 丰富的集合操作符
- 支持DSL
- 支持字面函数(lambdas)
更像是java的升级版,将大大提高开发效率。当然每个语言都有它的优势,这里没有黑java的意思,语言只是生产工具。作为一个有追求的coder,我们应该选择更加高效的方式,提高我们的核心竞争力,现在开始进入kotlin的学习之旅,对比java,从语法开始学习。
基本类型
与java相似
类型 | 位宽 |
---|---|
Double | 64 |
Float | 32 |
Long | 64 |
Int | 32 |
Short | 16 |
Byte | 8 |
可以使用下划线增加数值常量的可读性
1 | val oneMillion = 1_000_000 |
相等
装箱过的数值是不保留特征
参照相等(指向相同的对象)
结构相等(类型相同)
1 | val a: Int = 10000 |
== === 与 equals
==
- 如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等
- 如果作用于引用类型的变量,则比较的是所指向的对象的地址
===
- 对于基本数据类型,如果类型不同,其结果就是不等。如果同类型相比,与“==”一致,直接比较其存储的 “值”是否相等;
- 对于引用类型,与“==”一致,比较的是所指向的对象的地址
equals
- equals方法不能作用于基本数据类型的变量
- 如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
- 诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。
string的判断用==与equals均可
短类型和长类型间的转换
短类型是不会隐式转换为长类型的,需要显示转换
1 | val b: Byte = 1 // OK, 字面值常量会被静态检查 |
基本类型显示转换
toByte(): Byte
toShort(): Short
toInt(): Int
toLong(): Long
toFloat(): Float
toDouble(): Double
toChar(): Char
短类型加长类型会隐式转换为长类型
1 | val l = 1.toLong + 1 // Long + Int => Long |
数组
Kotlin 中由 Array
类表示,有 get
和 set
方法,以及 size
方法,以及一些常用的函数:
创建数组
1 | arrayOf(1, 2, 3)//创建一个int数组 |
原始类型提供的数组创建函数ByteArray
, ShortArray
, IntArray
1 | val x: IntArray = intArrayOf(1, 2, 3) |
定义包名
1 | package my.demo |
字符串
字符串的元素可以通过索引操作读取: s[i]
。字符串可以用 for 循环迭代:
1 | for (c in str) { |
多行string是由三个引号包裹的("""
),可以通过trim-margin()
函数移除空格,默认|作边界前缀,也可以选择其他符号比如trim-margin(>)
1 | val text = """ |
字符串模板
字符串可以包含模板表达式,即可求值的代码片段,并将其结果连接到字符串中。$变量名/表达式
1 | val s = "abc" |
注释
与java一样的单行和多行注释
1 | // 单行注释 |
空安全
不允许为空的string
1 | var a: String ="abc" |
允许为空的string
1 | var b: String? = "abc" |
调用的时候
1 | val l = a.length() |
java一样检查null
1 | if (b != null && b.length() >0) |
安全调用
1 | b?.length() |
如果 b 不为空则返回长度,否则返回空。这个表达式的的类型是Int?
链式调用中同样有效
1 | bob?.department?.head?.name |
Elvis 操作符
类似java中的三目运算符,b!=null?(b.length):-1
左边表达式不为空则返回,否则返回右边的表达式
1 | val l = b.length()?: -1 |
!! 操作符
NPE-lovers。 b!! ,会返回一个非空的 b 或者抛出一个 b 为空的 NPE(null pointer exception)
1 | val l = b !!.length() |
安全转换
java中普通的转换可能产生 ClassCastException 异常。另一个选择就是使用安全转换,如果不成功就返回空
1 | val aInt: Int? = a as? Int |
类型检查和转换
is !is 表达式
类似java中的instanceof
1 | if (obj is String) { |
智能转换
编译器会跟踪 is 检查静态变量,自动插入安全转换
1 | fun demo(x: Any) { |
不安全的转换符
使用as转换,如果转换是不被允许的那么转换符就会抛出一个异常。
1 | val x: String?= y as String? |
安全转换符
使用as?转换,不管 as? 右边的是不是一个非空 String 结果都会转换为可空的
1 | val x: String ?= y as? String |
流程控制
if表达式
1 | var max: Int |
When表达式
相当于java的switch,条件支持表达式,多变量可在同一分支处理,用逗号隔开
1 | when (x) { |
for循环
集合迭代
1 | for (item: Int in ints){ |
数组迭代,可通过索引,或者withIndex函数
1 | for ((index, value) in array.withIndex()) { |
while循环
与java语法类似
1 | while (x > 0) { |
Ranges
语法格式start..end
,in
标识符,在范围内的判断,!in
不在范围内,step
循环增量
反向遍历
downto
,语法格式 start downto end
reversed()
,语法格式(start..end).reversed()
1 | // Checking if value of comparable is in range. Optimized for number primitives. |