函数声明 使用 fun 关键字 参数使用 name: type
的形式表示 左边是参数的名字 右边是参数的类型,最后的冒号后面代表返回值的类型。如果这个函数没有返回值可以省略或者使用Unit 代替
fun double(x: Int): Int {
return 2 * x
}
参数可以有默认值 比如上面的( x : Int = 0)
用法:
val result = double(2)
当函数返回单个表达式时,可以省略花括号并且在 = 符号之后指定代码体即可:
fun double(x: Int): Int = x * 2
可变数量的参数(Varargs)
fun <T> asList(vararg ts: T): List<T> {
val result = ArrayList<T>()
for (t in ts) // ts is an Array
result.add(t)
return result
}
允许将可变数量的参数传递给函数:
val list = asList(1, 2, 3)
函数作用域
在 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())
}
局部函数可以访问外部函数(即闭包)的局部变量,所以在上例中,visited 可以是局部变量:
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 <T> singletonList(item: T): List<T> {
// ……
}
高阶函数
高阶函数是将函数用作参数或返回值的函数
Lambda 表达式
- lambda 表达式总是被大括号括着
- 其参数(如果有的话)在
->
之前声明(参数类型可以省略) - 函数体(如果存在的话)在
->
后面
高阶函数的另一个例子是 list中的map()方法
fun <T, R> List<T>.map(transform: (T) -> R): List<R> {
val result = arrayListOf<R>()
for (item in this)
result.add(transform(item))
return result
}
例子:
val ints = listOf<Int>(1,2,3,4,5,5)
//可以如下调用
val resmap = ints.map {
value -> value * 2
}
Log.i("resmap",resmap.toString());
//结果
12-18 13:54:32.147 9639-9639/com.chs.kotlintext I/resmap: [2, 4, 6, 8, 10, 10]
另一个有用的约定是,如果函数字面值只有一个参数, 那么它的声明可以省略(连同 ->),其名称是 it。
所以上面的例子可以写成
val resmap = ints.map {
it * 2
}
//返回值和上面一样
12-18 14:00:13.812 10038-10038/com.chs.kotlintext I/resmap: [2, 4, 6, 8, 10, 10]
内联函数
使用 inline 关键字
内联目前主要是应用在 函数参数是lambda表达式的代码中,可以提高高阶函数的效率
inline fun <T> lock(lock: Lock, body: () -> T): T {
// ……
}
inline修饰符影响函数本身和传给它的 lambda 表达式:所有这些都将内联到调用处。如果有两个以上的lambda参数,只想联一个怎么办,就用到了 noinline 关键字
inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) {
// ……
}
协程
在 Kotlin 1.1+ 中协程是实验性的
关于协程的内容很多
https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md
简单例子
项目build.gradle文件中加入下面引用
compile 'org.jetbrains.kotlinx:kotlinx-coroutines-core:0.20'
launch 在不阻塞当前线程的情况下启动新协程,并将协程的引用作为Job返回。当作业被取消时,协程被取消。
launch { // 在后台启动新的协程并继续
delay(1000L) // 非阻塞延迟1秒(默认时间单位是ms)
Log.i("launch","World") // 延迟后打印
}
Log.i("launch","Hello") // 主线程在协程延迟的时候继续
打印结果:
12-18 16:52:25.827 17383-17383/com.chs.kotlintext I/launch: Hello
12-18 16:52:26.831 17383-17428/com.chs.kotlintext I/launch: World