kotlin-安卓开发笔记
基本语法
函数定义
函数定义使用关键字fun,参数格式为:参数 : 类型
1 | fun sum(a: Int, b: Int): Int { // Int 参数,返回值 Int |
表达式作为函数体,返回类型自动推断:
1 | fun sum(a: Int, b: Int) = a + b |
1 | fun printSum(a: Int, b: Int): Unit { |
可变长参数函数的变长参数可以用 vararg 关键字进行标识:
1 | fun vars(vararg v:Int){ |
lambda(匿名函数)
1 | // 测试 |
定义常量与变量
可变变量定义:var
关键字var
<标识符> : <类型> = <初始化值>
不可变变量定义:val
关键字,只能赋值一次的变量(类似Java中final修饰的变量)val
<标识符> : <类型> = <初始化值>
常量与变量都可以没有初始化值,但是在引用前必须初始化
编译器支持自动类型判断,即声明时可以不指定类型,由编译器判断。
1 | val a: Int = 1 |
注释
Kotlin 支持单行和多行注释,与 Java 不同, Kotlin 中的块注释允许嵌套。实例如下:
1 | // 这是一个单行注释 |
字符串模板
$
表示一个变量名或者变量值
$varName
表示变量值
${varName.fun()}
表示变量的方法返回值:
1 | var a = 1 |
基本数据类型
Kotlin 的基本数值类型包括 Byte、Short、Int、Long、Float、Double 等。不同于 Java 的是,字符不属于数值类型,是一个独立的数据类型。
类型 | 位宽度 |
---|---|
Double | 64 |
Float | 32 |
Long | 64 |
Int | 32 |
Short | 16 |
Byte | 8 |
字面常量
下面是所有类型的字面常量:
十进制:123
长整型以大写的 L 结尾:123L
16 进制以 0x 开头:0x0F
2 进制以 0b 开头:0b00001011
注意:8进制不支持
Kotlin 同时也支持传统符号表示的浮点数值:
Doubles 默认写法: 123.5, 123.5e10
Floats 使用 f 或者 F 后缀:123.5f
你可以使用下划线使数字常量更易读:
val oneMillion = 1_000_000
val creditCardNumber = 1234_5678_9012_3456L
val socialSecurityNumber = 999_99_9999L
val hexBytes = 0xFF_EC_DE_5E
val bytes = 0b11010010_01101001_10010100_10010010
比较两个数字
Kotlin 中没有基础数据类型,只有封装的数字类型,你每定义的一个变量,其实 Kotlin 帮你封装了一个对象,这样可以保证不会出现空指针。数字类型也一样,所以在比较两个数字的时候,就有比较数据大小和比较两个对象是否相同的区别了。
在 Kotlin 中,三个等号 === 表示比较对象地址,两个 == 表示比较两个值大小。
1 | fun main(args: Array<String>) { |
类型转换
由于不同的表示方式,较小类型并不是较大类型的子类型,较小的类型不能隐式转换为较大的类型。 这意味着在不进行显式转换的情况下我们不能把 Byte 型值赋给一个 Int 变量。
1 | val b: Byte = 1 // OK, 字面值是静态检测的 |
每种数据类型都有下面的这些方法,可以转化为其它的类型:
1 | toByte(): Byte |
有些情况下也是可以使用自动类型转化的,前提是可以根据上下文环境推断出正确的数据类型而且数学操作符会做相应的重载。例如下面是正确的:
val l = 1L + 3 // Long + Int => Long
位操作符
对于Int和Long类型,还有一系列的位操作符可以使用,分别是:
1 | shl(bits) – 左移位 (Java’s <<) |
字符
和 Java 不一样,Kotlin 中的 Char 不能直接和数字操作,Char 必需是单引号 ‘ 包含起来的。比如普通字符 ‘0’,’a’。
1 | fun check(c: Char) { |
字符字面值用单引号括起来: ‘1’。 特殊字符可以用反斜杠转义。 支持这几个转义序列:\t、 \b、\n、\r、'、"、\ 和 $。 编码其他字符要用 Unicode 转义序列语法:’\uFF00’。
我们可以显式把字符转换为 Int 数字:
1 | fun decimalDigitValue(c: Char): Int { |
当需要可空引用时,像数字、字符会被装箱。装箱操作不会保留同一性。
布尔
布尔用 Boolean 类型表示,它有两个值:true 和 false。
若需要可空引用布尔会被装箱。
内置的布尔运算有:
1 | || – 短路逻辑或 |
数组
数组用类 Array 实现,并且还有一个 size 属性及 get 和 set 方法,由于使用 [] 重载了 get 和 set 方法,所以我们可以通过下标很方便的获取或者设置数组对应位置的值。
数组的创建两种方式:一种是使用函数arrayOf();另外一种是使用工厂函数。如下所示,我们分别是两种方式创建了两个数组:
1 | fun main(args: Array<String>) { |
如上所述,[] 运算符代表调用成员函数 get() 和 set()。
注意: 与 Java 不同的是,Kotlin 中数组是不协变的(invariant)。
除了类Array,还有ByteArray, ShortArray, IntArray,用来表示各个类型的数组,省去了装箱操作,因此效率更高,其用法同Array一样:
1 | val x: IntArray = intArrayOf(1, 2, 3) |
字符串
和 Java 一样,String 是不可变的。方括号 [] 语法可以很方便的获取字符串中的某个字符,也可以通过 for 循环来遍历:
1 | for (c in str) { |
Kotlin 支持三个引号 “”” 扩起来的字符串,支持多行字符串,比如:
1 | fun main(args: Array<String>) { |
String 可以通过 trimMargin() 方法来删除多余的空白。
1 | fun main(args: Array<String>) { |
默认 | 用作边界前缀,但你可以选择其他字符并作为参数传入,比如 trimMargin(“>”)。
字符串模板
字符串可以包含模板表达式 ,即一些小段代码,会求值并把结果合并到字符串中。 模板表达式以美元符($)开头,由一个简单的名字构成:
1 | fun main(args: Array<String>) { |
或者用花括号扩起来的任意表达式:
1 | fun main(args: Array<String>) { |
原生字符串和转义字符串内部都支持模板。 如果你需要在原生字符串中表示字面值 $ 字符(它不支持反斜杠转义),你可以用下列语法:
1 | fun main(args: Array<String>) { |
线程
在 kotlin中,有三种方式可以创建线程
继承Thread类
1
2
3
4
5object : Thread() {
override fun run() {
println("running from Thread: ${Thread.currentThread()}")
}
}.start()使用Runnable类初始化Thread对象。
1
2
3Thread({
println("running from lambda: ${Thread.currentThread()}")
}).start()这里我们并没有看到,Runnable对象。其实是被lambda表达式替换了。
使用kotlin提供的封装方法
1
2
3thread(start = true) {
println("running from thread(): ${Thread.currentThread()}")
}
线程休眠和锁
kotlin的基类是Any,类似于java中的Object,但是没有提供wait()、notify()、notifyAll()方法。但是我们依然可以通过创建Object的实例,从而调用wait()、notify()、notifyAll()方法。
1 | private val lock = java.lang.Object() |
线程休眠
1 | Thread.sleep(millis) |