Kotlin进阶实战
上QQ阅读APP看书,第一时间看更新

2.1.2 函数

1.返回Unit的函数

跟Java不同,Kotlin没有void,但是函数总会返回一个值。如果一个函数不返回任何类型的对象,那么该函数返回的是Unit类型。

例如:

     fun printHello(): Unit {
        println("Hello World")
     }

Unit返回值可以被省略:

     fun printHello() {
        println("Hello World")
     }

2.返回Nothing的函数

跟Unit相比,容易混淆的是Nothing。Unit会返回Unit的单例,而通过阅读Nothing的源码,发现它永远都不会返回任何东西。

在Nothing的表达式之后,所有代码都是无法执行的。throw表达式的类型是一个特殊的类型Nothing。

下面定义的doForever函数返回Nothing类型,因此它后面打印的"done"语句永远不会被执行。

3.单表达式函数

当函数返回单个表达式时,可以省略函数体的花括号,例如:

     fun sum(x: Int=0, y: Int): Int {
        return x + y
     }

等价于:

     fun sum(x: Int=0, y: Int): Int =  x + y

它还等价于:

     fun sum(x: Int=0, y: Int) =  x + y

因为Kotlin可以通过编译器来推断该函数的返回类型。

4.成员函数

成员函数是指在类或对象内部定义的函数,这一点跟Java中的概念是一致的。

5.局部函数(Local Function)

所谓局部函数,是指在一个函数中定义另一个函数。有点类似于内部类,局部函数可以访问外部函数的局部变量,甚至是闭包。

例如下面的代码,在validate函数中定义了validateInput函数,validateInput函数用来进行字符串的校验,帮助我们消除重复的代码。另外,还定义了一个printPerson函数,它也包含一个局部函数print()用于打印Person信息。print()函数直接访问了它的外部函数printPerson()的局部变量。

6.尾递归函数

来自维基百科的定义:在计算机科学中,尾调用是指一个函数的最后一个动作是一个函数调用的情形,即这个调用的返回值直接被当前函数返回的情形。这种情形下称该调用位置为尾位置。若这个函数在尾位置调用本身(或者一个尾调用本身的其他函数等),则称这种情况为尾递归,是递归的一种特殊情形。尾调用不一定是递归调用,但是尾递归特别有用,也比较容易实现。

使用递归对自然数求和:

执行上述代码,会出现“Exception in thread "main" java.lang.StackOverflowError”。

这是因为在Kotlin中使用尾递归函数需要满足两个条件:

· 使用tailrec关键词修饰函数。

· 在函数最后进行递归调用。

使用tailrec关键词之后,编译器会优化该递归,从而避免堆栈溢出的风险。

对上述代码稍作修改:

此时,执行结果如下:

     705082704

而我们目前使用比较多的Java 8并不能在编译器级别直接支持尾部调用优化,只能通过Lambda方式实现。

7.Top level函数

相对于在Java中所有的内容都必须在类中定义,Kotlin允许直接在.kt文件中定义任何类定义之外的top-level函数。

top-level函数的默认修饰符是public,因此这些函数可以在任何位置被访问。例如定义如下的函数:

     @Throws(IOException::class)
     fun readFileToString(file: File): String = file.readText()

Java程序想要调用readFileToString()方法,必须通过文件名Kt.readFileToString(f)才可以调用。或者在文件头添加:

     @file:JvmName("FileUtils")

这样一来,Java程序可以通过FileUtils.readFileToString(f)进行调用。

让我们来小结一下Kotlin相关的top-level,如表2-1所示。

表2-1 Kotlin相关的top-level

8.无参的main函数

Kotlin程序的入口一般会采用main函数,例如:

     fun main(args: Array<String>) {
        println("Hello Kotlin")
     }

Kotlin 1.3之后引入了一种更简单的无参main函数,简化了main函数的写法:

     fun main() {
        println("Hello Kotlin")
     }