zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Kotlin之基本语法详解手机开发

Kotlin手机开发 详解 基本 语法
2023-06-13 09:20:13 时间

在今年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 null 


fun printLength(obj: Any) { println("$obj string length is ${getStringLength(obj) ?: "... err, not a string"} ") printLength("Incomprehensibilities") printLength(1000) printLength(listOf(Any())) }
for循环

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程序应用开发手机开发无线开发移动端开发