1.变量
Kotlin中有两个关键字定义变量 var 和 val
val是一个只读变量,这种声明变量的方式相当于java中的final变量。一个val创建的时候必须初始化,因为以后不能被改变。
var是一个可变变量,这是一个可以通过重新分配来更改为另一个值的变量。这种声明变量的方式和Java中声明变量的方式一样。
const关键字: const修饰的val变量相当于java中 static final
是真正意义上的java常量
2.常量 Byte Char Short Int Double Long Float
十进制:123
长整型以大写的 L 结尾:123L
16 进制以 0x 开头:0x0F
2 进制以 0b 开头:0b00001011 注意:8进制不支持
Doubles 默认写法: 123.5, 123.5e10
Float使用 f 或者 F 后缀:123.5f
布尔 Boolean 值是: true 或 false 内置的布尔运算有:|| – 短路逻辑或 && – 短路逻辑与 ! - 逻辑非
kotlin中写法 toInt() 对应 java 中写法 Int.valueof();
Kotlin 1.3 引入了无符号整型类型:
kotlin.UByte
: 无符号 8 比特整数,范围是 0 到 255kotlin.UShort
: 无符号 16 比特整数,范围是 0 到 65535kotlin.UInt
: 无符号 32 比特整数,范围是 0 到 2^32 - 1kotlin.ULong
: 无符号 64 比特整数,范围是 0 到 2^64 - 1
// 可以使用字面值后缀定义无符号类型:
val uint = 42u
val ulong = 42uL
val ubyte: UByte = 255u
// 通过标准库扩展可以将有符号类型转换为无符号类型,反之亦然:
val int = uint.toInt()
val byte = ubyte.toByte()
val ulong2 = byte.toULong()
// 无符号类型支持类似的操作符:
val x = 20u + 22u
val y = 1u shl 8
val z = "128".toUByte()
val range = 1u..5u
println("ubyte: $ubyte, byte: $byte, ulong2: $ulong2")
println("x: $x, y: $y, z: $z, range: $range")
结果:
ubyte: 255, byte: -1, ulong2: 18446744073709551615
x: 42, y: 256, z: 128, range: 1..5
3.空(Null)
1.可空类型与非空类型
常规初始化意味着非空,不能重新赋值为空;
如果要允许为空,我们可以声明一个变量为可空字符串,写作 String?
:
var b: String? = "abc" // 可以设置为空
b = null // ok
print(b)
2.安全的调用
选择是安全调用操作符,写作 ?.
val a = "Kotlin"
val b: String? = null
println(b?.length)
println(a?.length) // 无需安全调用
如果 b
非空,就返回 b.length
,否则返回 null,这个表达式的类型是 Int?
。
再比如:bob?.department?.head?.name 如果其中有一个属性为空 返回null,
安全调用也可以出现在赋值的左侧。这样,如果调用链中的任何一个接收者为空都会跳过赋值,而右侧的表达式根本不会求值
// 如果 `person` 或者 `person.department` 其中之一为空,都不会调用该函数:
person?.department?.head = managersPool.getManager()
3.Elvis 操作符
val l: Int = if (b != null) b.length else -1 也可以写成
val l = b?.length ?: -1
如果 ?:
左侧表达式非空,elvis 操作符就返回其左侧表达式,否则返回右侧表达式。 请注意,当且仅当左侧为空时,才会对右侧表达式求值。
fun foo(node: Node): String? {
val parent = node.parentNode ?: return null
// ?:如果 ?: 左侧表达式非空,elvis 操作符就返回其左侧表达式,否则返回右侧表达式。 请注意,当且仅当左侧为空时,才会对右侧表达式求值。
val name = node.nodeName?: throw IllegalArgumentException("name expected")
// ……
return null;
}
4.!!
操作符 非空类型 不允许为空,不然会报错 空指针(NPE)异常
var b=""
val l = b!!.length// !! 非空类型
print(l)
5.类型的安全转换
如果对象不是目标类型,那么常规类型转换可能会导致 ClassCastException
。 另一个选择是使用安全的类型转换,如果尝试转换不成功则返回 null。使用: as?
//安全类型转换
//如果对象不是目标类型,那么常规类型转换可能会导致 ClassCastException。 另一个选择是使用安全的类型转换,
// 如果尝试转换不成功则返回 null:
var a=null
val aInt: Int? = a as Int
print(aInt)
结果:null
如果去掉 ?,测试结果: 抛出ClassCastException异常
6.可空类型的集合
如果你有一个可空类型元素的集合,并且想要过滤非空元素,你可以使用 filterNotNull
来实现:
val nullableList: List<Int?> = listOf(1, 2, null, 4)
val intList: List<Int> = nullableList.filterNotNull()
fun bar(x: String?) {
if (!x.isNullOrEmpty()) {//判断非空或者null
println("length of '$x' is ${x.length}") // 智能转换为非空!
}
}
4.字符
和 Java 不一样,Kotlin 中的 Char 不能直接和数字操作,Char 必需是单引号”包含起来的。
比如普通字符 ‘0’,’a’。
fun check(c: Char) {
if (c == 1) { // 错误:类型不兼容
// ……
}
}
字符字面值用单引号括起来: ‘1’。 特殊字符可以用反斜杠转义。 支持这几个转义序列:\t、 \b、\n、\r、\’、\”、\ 和 $。 编码其他字符要用 Unicode 转义序列语法:’\uFF00’。
我们可以显式把字符转换为 Int 数字:
fun decimalDigitValue(c: Char): Int {
if (c !in '0'..'9')
throw IllegalArgumentException("Out of range")
return c.toInt() - '0'.toInt() // 显式转换为数字
}
5.字符串
和 Java 一样,String 是可不变的。方括号 [] 语法可以很方便的获取字符串中的某个字符,也可以通过 for 循环来遍历:
Kotlin 支持三个引号 “”” 扩起来的字符串,支持多行字符串,
比如:
fun main(args: Array<String>) {
val text = """
多行字符串
多行字符串
"""
println(text) // 输出有一些前置空格
}
String 可以通过 trimMargin() 方法来删除多余的空白。
fun main(args: Array<String>) {
val text = """
|多行字符串
|多行字符串
|多行字符串
|Runoob
""".trimMargin()
println(text) // 前置空格删除了
}
默认 | 用作边界前缀,但你可以选择其他字符并作为参数传入,比如 trimMargin(“>”)。
6.区间
区间表达式由具有操作符形式 .. 的 rangeTo 函数辅以 in 和 !in 形成。
for (i in 1..4) print(i) // 输出“1234”
for (i in 4..1) print(i) // 什么都不输出
for (i in 1..10) { // 等同于 1 <= i && i <= 10
println(i)
}
/ 使用 step 指定步长
for (i in 1..4 step 2) print(i) // 输出“13”
for (i in 4 downTo 1 step 2) print(i) // 输出“42” //从4到1
// 使用 until 函数排除结束元素
for (i in 1 until 10) { // i in [1, 10) 排除了 10
println(i)
}
// 使用 until 函数排除结束元素
for (i in 1 until 6) { // i in [1, 4) 排除了 4
print(i)
}
7.类型检测及自动类型转换
使用 is 运算符检测一个表达式是否某类型的一个实例(类似于Java中的instanceof关键字)。
fun getStringLength(obj: Any): Int? {
if (obj is String) {
// 做过类型判断以后,obj会被系统自动转换为String类型
return obj.length
}
//在这里还有一种方法,与Java中instanceof不同,使用!is
// if (obj !is String){
// // XXX
// }
// 这里的obj仍然是Any类型的引用
return null
}
8.数组
数组用类 Array 实现,并且还有一个 size 属性及 get 和 set 方法,由于使用 [] 重载了 get 和 set 方法,所以我们可以通过下标很方便的获取或者设置数组对应位置的值。
数组的创建两种方式:一种是使用函数arrayOf();另外一种是使用工厂函数。如下所示,我们分别是两种方式创建了两个数组
fun main(args: Array<String>) {
//[1,2,3]
val a = arrayOf(1, 2, 3)
//[0,2,4]
val b = Array(3, { i -> (i * 2) })
//读取数组内容
println(a[0]) // 输出结果:1
println(b[1]) // 输出结果:2
}
如上所述,[] 运算符代表调用成员函数 get() 和 set()。
注意: 与 Java 不同的是,Kotlin 中数组是不型变的(invariant)。
除了类Array,还有ByteArray, ShortArray, IntArray,用来表示各个类型的数组,省去了装箱操作,因此效率更高,其用法同Array一样
val x: IntArray = intArrayOf(1, 2, 3)
x[0] = x[1] + x[2]
9.集合
Kotlin没有采用它自己的集合类,而是采用标准的Java集合类。大部分Kotlin的标准库是由Java类的拓展函数组成的。
Kotlin中对集合增加了一个新的接口MutableList,实现该接口的集合是可变集合。Kotlin中,集合分为可变集合和不可变集合。
创建不可变集合 只有get 方法 不能修改集合中数据。
创建可变集合 有set和 get 方法,可以修改集合数据
val list2 = arrayListOf<Int>(1, 2, 3, 4)
list2.set(0, 10)
list2[0] = 11
list2.add(5)
println("list2 = $list2")
val list3 = mutableListOf("a", "b", "c")
list3.add("d")
println("e = $list3")
println("last element = ${list3.last()}")