基本语法:
1 定义函数
fun sum(a: Int , b: Int) : Int{ return a + b }
这种就是较传统的方式,有参数类型 已经返回值类型
简洁版:
fun sum(a: Int, b: Int) = a + b
省略掉返回值类型和花括号,由系统自行判断返回值类型
无返回值函数:
fun printSum(a: Int, b: Int): Unit { println("sum of $a and $b is ${a + b}") }
简洁版:
fun printSum(a: Int, b: Int) { println("sum of $a and $b is ${a + b}") }
2 定义局部变量
常量:
fun main(args: Array<String>) { val a: Int = 1 // 立即初始化 val b = 2 // 推导出Int型 val c: Int // 当没有初始化值时必须声明类型 c = 3 // 赋值 println("a = $a, b = $b, c = $c") }
变量:
fun main(args: Array<String>) { var x = 5 // 推导出Int类型 x += 1 println("x = $x") }
3 注释
与 java 和 javaScript 一样,Kotlin 支持单行注释和块注释。
// 单行注释
/* 哈哈哈哈
这是块注释 */
与 java 不同的是 Kotlin 的 块注释可以级联。
4 使用字符串模板
fun main(args: Array<String>) { var a = 1 // 使用变量名作为模板: val s1 = "a is $a" a = 2 // 使用表达式作为模板: val s2 = "${s1.replace("is", "was")}, but now is $a" println(s2) }
这一点比较有意思,如果需要取变量值的时候是用的$a来表示,而跟java中的直接使用变量名不一样了
5 流程控制
val max = if (a > b){ print("Choose a") a } else{ print("Choose b") b }
这个比较有意思,我觉得kotlin最大的亮点就是把所有的句尾分号去掉了,这个流程相当于是直接return返回值
when 取代了 C 风格语言的 switch 。最简单的用法像下面这样
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> { //Note the block
print("x is neither 1 nor 2")
}
}
如果有分支可以用同样的方式处理的话,分支条件可以连在一起:
when (x) {
0,1 -> print("x == 0 or x == 1")
else -> print("otherwise")
}
可以用任意表达式作为分支的条件
when (x) {
parseInt(s) -> print("s encode x")
else -> print("s does not encode x")
}
甚至可以用 in 或者 !in 检查值是否值在一个集合中:
when (x) {
in 1..10 -> print("x is in the range")
in validNumbers -> print("x is valid")
!in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}
也可以用 is 或者 !is 来判断值是否是某个类型。注意,由于 smart casts ,你可以不用另外的检查就可以使用相应的属性或方法。
val hasPrefix = when (x) {
is String -> x.startsWith("prefix")
else -> false
}
when 也可以用来代替 if-else if 。如果没有任何参数提供,那么分支的条件就是简单的布尔表达式,当条件为真时执行相应的分支:
when {
x.isOdd() -> print("x is odd")
x.isEven() -> print("x is even")
else -> print("x is funny")
}
fun test() {
val result = try {
count()
}catch (e: ArithmeticException) {
throw IllegaStateException(e)
}
//处理 result
}
for 循环通过任何提供的迭代器进行迭代。语法是下面这样的:
for (item in collection)
print(item)
内容可以是一个语句块
for (item: Int in ints){
//...
}
6 空安全
在 Kotlin 类型系统中可以为空和不可为空的引用是不同的。比如,普通的 String
类型的变量不能为空:
var a: String ="abc"
a = null //编译错误
允许为空,我们必须把它声明为可空的变量:
var b: String? = "abc"
b = null
现在你可以调用 a 的方法,而不用担心 NPE 异常了:
val l = a.length()
但如果你想使用 b 调用同样的方法就有可能报错了:
val l = b.length() //错误:b 不可为空
但我们任然想要调用方法,有些办法可以解决。
首先,你可以检查 b
是否为空,并且分开处理下面选项:
val l = if (b != null) b.length() else -1
编译器会跟踪你检查的信息并允许在 if 中调用 length()。更复杂的条件也是可以的:
if (b != null && b.length() >0)
print("Stirng of length ${b.length}")
else
print("Empty string")
注意只有在 b 是不可变时才可以
第二个选择就是使用安全操作符,?.
:
b?.length()
如果 b 不为空则返回长度,否则返回空。这个表达式的的类型是 Int?
安全调用在链式调用是是很有用的。比如,如果 Bob 是一个雇员可能分配部门(也可能不分配),如果我们想获取 Bob 的部门名作为名字的前缀,就可以这样做:
bob?.department?.head?.name
这样的调用链在任何一个属性为空都会返回空。
当我们有一个 r 的可空引用时,我们可以说如果 r
不空则使用它,否则使用使用非空的 x :
val l: Int = if (b != null) b.length() else -1
尽管使用 if 表达式我们也可以使用 Elvis 操作符,?:
val l = b.length()?: -1
如果 ?: 左边表达式不为空则返回,否则返回右边的表达式。注意右边的表带式只有在左边表达式为空是才会执行
注意在 Kotlin 中 throw return 是表达式,所以它们也可以在 Elvis 操作符右边。这是非常有用的,比如检查函数参数是否为空;
fun foo(node: Node): String? {
val parent = node.getParent() ?: return null
val name = node.getName() ?: throw IllegalArgumentException("name expected")
//...
}
第三个选择是 NPE-lovers。我们可以用 b!! ,这会返回一个非空的 b 或者抛出一个 b 为空的 NPE
val l = b !!.length()
普通的转换可能产生 ClassCastException
异常。另一个选择就是使用安全转换,如果不成功就返回空:
val aInt: Int? = a as? Int
7 Ranges
范围内迭代和步进
if (i in 1..10) { // equivalent of 1 <= i && i <= 10 println(i)}
for (i in 1..4) print(i) // prints "1234"
for (i in 4..1) print(i) // prints nothing
for (i in 4 downTo 1) print(i) // prints "4321"
for (i in 1..4 step 2) print(i) // prints "13"
for (i in 4 downTo 1 step 2) print(i) // prints "42"
for (i in 1 until 10) { // i in [1, 10), 10 is excluded
println(i)}
这些在循环中非常实用,注释已经讲的很明白啦