Kotlin之基本语法详解手机开发
在今年Google IO大会上Google已经明确kotlin作为为Android第一官方语言的地位。我相信Google的决意,就像当初毫不犹豫的抛弃eclipse转向as,kotlin已经是不可避免的大势所趋了。再加上Kotlin与java代码完全兼容,所以从Java转向Kotlin是一件很容易的事情。Kotlin语法简单,它融合了当前多种语言的优势,可以是一门明星语言。
下面就Kotlin的一些基本语法做一个讲解。
一个源文件往往以包声明开始:源文件的所有内容(比如类和函数)都被包声明并包括。
package foo.bar fun bza() {} class Goo {}
在上面的例子中, bza() 的全名应该是 foo.bar.bza ,Goo 的全名是 foo.bar.Goo。如果没有指定包名,那这个文件的内容就从属于一个默认的 “default” 包。
Imports在源文件中,除了模块中默认导入的包,每个文件也可以有它自己的导入指令。比如:
import foo.Bar
如果不指定特定的文件,那么可以使用*导入范围内的所有可用的内容 (包,类,对象,等等)。比如:
import foo.* //foo 中的所有内容
如果命名有冲突,我们还可以使用 as 关键字局部重命名解决冲突。
import foo.Bar // Bar 可以使用 import bar.Bar as bBar // bBar 代表 bar.Bar
在 kotlin 中用关键字 fun 声明函数:
fun double(x: Int): Int { }
函数参数用 Pascal 符号定义,格式形如:name:type,参数之间用逗号隔开,每个参数必须指明类型。
fun powerOf(number: Int, exponent: Int) { }
函数参数可以设置默认值,默认值可以通过在type类型后使用=号进行赋值,当参数被忽略时会使用默认值,这样做的好处是可以减少重载。
fun read(b: Array Byte , off: Int = 0, len: Int = b.size() ) { }
在函数内部可以直接使用函数,比如:
val result = double(2)
如果在其他类需要调用调用成员函数:
Sample().foo() // 创建Sample类的实例,调用foo方法
在满足如下条件时:它们是成员函数或者是扩展函数,只有一个参数 使用infix关键词进行标记。函数可以通过中缀符号进行调用。比如:
//给 Int 定义一个扩展方法 infix fun Int.shl(x: Int): Int { 1 shl 2 //用中缀注解调用扩展函数 1.shl(2)Unit类型
如果函数不会返回任何有用值,那么他的返回类型就是 Unit 。Unit 是一个只有唯一值Unit的类型,这个值并不需要被直接返回,相当于Java的Void。
fun printHello(name: String?): Unit { if (name != null) println("Hello ${name}") else println("Hi there!") // `return Unit` or `return` is optional }
Unit 返回值也可以省略,例如下面这样:
fun printHello(name: String?) { ... }单表达式函数
当函数只返回单个表达式时,大括号可以省略,并在 = 后面定义函数体:
fun double(x: Int): Int = x*2
如果进一步精简,还可以写成如下的方式。
fun double(x: Int) = x * 2
函数的参数(通常是最后一个参数)可以用 vararg 修饰符进行标记,标记后,允许给函数传递可变长度的参数:
fun asList T (vararg ts: T): List T { val result = ArrayList T () for (t in ts) result.add(t) return result
val list = asList(1, 2, 3)
可变函数只有一个参数可以被标注为 vararg 。加入vararg并不是列表中的最后一个参数,那么后面的参数需要通过命名参数语法进行传值,再或者如果这个参数是函数类型,就需要通过lambda法则。
当调用变长参数的函数时,我们可以一个一个的传递参数,比如:
asList(1, 2, 3)
或者我们要传递一个 array 的内容给函数,那么就可以使用 * 前缀操作符:
val a = array(1, 2, 3) val list = asList(-1, 0, *a, 4)
Kotlin 中可以在文件顶级声明函数,这就意味者你不用像在Java,C#或是Scala一样创建一个类来持有函数。除了顶级函数,Kotlin 函数可以声明为局部的,作为成员函数或扩展函数。
Kotlin 支持局部函数,比如在一个函数包含另一函数。
fun dfs(graph: Graph) { fun dfs(current: Vertex, visited: Set Vertex ) { if (!visited.add(current)) return for (v in current.neighbors) dfs(v, visited) dfs(graph.vertices[0], HashSet()) }
当然,局部函数可以访问外部函数的局部变量(比如闭包)。
fun dfs(graph: Graph) { val visited = HashSet Vertex () fun dfs(current: Vertex) { if (!visited.add(current)) return for (v in current.neighbors) dfs(v) dfs(graph.vertices[0]) }
局部函数甚至可以返回到外部函数。
fun reachable(from: Vertex, to: Vertex): Boolean { val visited = HashSet Vertex () fun dfs(current: Vertex) { if (current == to) return@reachable true if (!visited.add(current)) return for (v in current.neighbors) dfs(v) dfs(from) return false }
Kotlin和Java一样,还支持泛型函数。
fun sigletonArray T (item: T): Array T { return Array T (1, {item}) }尾递归函数
Kotlin 支持函数式编程的尾递归。这个允许一些算法可以通过循环而不是递归解决问题,从而避免了栈溢出。当函数被标记为 tailrec 时,编译器会优化递归,并用高效迅速的循环代替它。
tailrec fun findFixPoint(x: Double = 1.0): Double = if (x == Math.cos(x)) x else findFixPoint(Math.cos(x))
这段代码计算的是数学上的余弦不动点。Math.cos 从 1.0 开始不断重复,直到值不变为止,结果是 0.7390851332151607。上面的代码等效于:
private fun findFixPoint(): Double { var x = 1.0 while (true) { val y = Math.cos(x) if ( x == y ) return y x = y }
注:使用 tailrec 修饰符必须在最后一个操作中调用自己。在递归调用代码后面是不允许有其它代码的,并且也不可以在 try/catch/finall 块中进行使用。当前的尾递归只在 JVM 的后端中可以用。
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) }条件表达式
fun maxOf(a: Int, b: Int): Int { if (a b) { return a } else { return b fun main(args: Array String ) { println("max of 0 and 42 is ${maxOf(0, 42)}") }
上面的表达式可简写为:
fun maxOf(a: Int, b: Int) = if (a b) a else b fun main(args: Array String ) { println("max of 0 and 42 is ${maxOf(0, 42)}") }值检查与自动转换
使用 is 操作符检查一个表达式是否是某个类型的实例。如果对不可变的局部变量或属性进行过了类型检查,就没有必要明确转换:
fun getStringLength(obj: Any): Int? { if (obj is String) { // obj 将会在这个分支中自动转换为 String 类型 return obj.length // obj 在种类检查外仍然是 Any 类型 return nullfor循环
fun printLength(obj: Any) { println("$obj string length is ${getStringLength(obj) ?: "... err, not a string"} ") printLength("Incomprehensibilities") printLength(1000) printLength(listOf(Any())) }
Kotlin简化了for循环的方式,例如:
fun main(args: Array String ) { val items = listOf("apple", "banana", "kiwi") for (item in items) { println(item) //或者使用下面的方式 //for (index in items.indices) { // println("item at $index is ${items[index]}") //} }while 循环
fun main(args: Array String ) { val items = listOf("apple", "banana", "kiwi") var index = 0 while (index items.size) { println("item at $index is ${items[index]}") index++ }ranges
检查 in 操作符检查数值是否在某个范围内:
fun main(args: Array String ) { val x = 10 val y = 9 if (x in 1..y+1) { println("fits in range") }
检查数值是否在范围外:
fun main(args: Array String ) { val list = listOf("a", "b", "c") if (-1 !in 0..list.lastIndex) { println("-1 is out of range") if (list.size !in list.indices) { println("list size is out of valid list indices range too") }
在范围内迭代:
fun main(args: Array String ) { for (x in 1..5) { print(x) }
或者使用步进:
fun main(args: Array String ) { for (x in 1..10 step 2) { print(x) for (x in 9 downTo 0 step 3) { print(x) }
对一个集合进行迭代:
fun main(args: Array String ) { val items = listOf("apple", "banana", "kiwi") for (item in items) { println(item) }
使用 in 操作符检查集合中是否包含某个对象。
fun main(args: Array String ) { val items = setOf("apple", "banana", "kiwi") when { "orange" in items - println("juicy") "apple" in items - println("apple is fine too") }
使用lambda表达式过滤和映射集合:
fun main(args: Array String ) { val fruits = listOf("banana", "avocado", "apple", "kiwi") fruits .filter { it.startsWith("a") } .sortedBy { it } .map { it.toUpperCase() } .forEach { println(it) } }
附:高阶函数和lambda表达式
5525.html
app程序应用开发手机开发无线开发移动端开发相关文章
- android Kotlin int类型和Long类型转换
- 把 "格子衫" 改造得更时尚 | Kotlin & Jetpack 最佳实践技巧
- Kotlin Flow响应式编程,基础知识入门
- 用kotlin来开发一个cli工具 | 没用的技能+1
- Kotlin安卓开发学习(2)
- Kotlin安卓开发学习(4)
- 【Kotlin】Kotlin 领域特定语言 DSL 原理 一 ( DSL 简介 | 函数 / 属性扩展 )
- 【Kotlin】Kotlin 类的继承 三 ( super 关键字使用 | super@ 外部调用父类方法 | 子类选择性调用 父类 / 接口 方法 super )
- 【Android NDK 开发】Kotlin 语言中使用 NDK ( 创建支持 Kotlin 的 NDK 项目 | Kotlin 语言中使用 NDK 要点 | 代码示例 )
- 【Kotlin 协程】协程底层实现 ② ( 协程调度器 | 协程任务泄漏 | 结构化并发 )
- 【Kotlin 协程】协程启动 ⑤ ( 协程作用域构建器 | runBlocking 函数 | coroutineScope 函数 | supervisorScope 函数 )
- 【Kotlin 协程】协程异常处理 ⑤ ( 异常传播的特殊情况 | 取消子协程示例 | 子协程抛出异常后父协程处理异常时机示例 | 异常聚合 | 多个子协程抛出的异常会聚合到第一个异常中 )
- 【Kotlin 协程】Flow 异步流 ④ ( 流的构建器函数 | flow 构建器函数 | flowOf 构建器函数 | asFlow 构建器函数 )
- 【Kotlin】集合操作 ⑤ ( Map 集合 | 获取 Map 值 | Map 遍历 | 可变 Map 集合 )
- 【Kotlin】Kotlin 与 Java 互操作 ② ( @JvmField 注解字段给 Java | @JvmOverloads 注解修饰函数 | @JvmStatic 注解声明静态成员 )
- 【错误记录】Android Studio 编译报错 ( To use data binding annotations in Kotlin, apply the ‘kotlin-kapt‘ plu )