【函数声明】
可见性修饰符 关键字 函数名称 (参数列表) : 返回值类型 {函数体}
- 用于创建类实例的工厂函数可以与抽象返回类型具有相同的名称。
public fun getNum(x:Int, y:Int): Int{
return x + y
}
//工厂函数
interface Foo
class FooImpl : Foo
fun Foo(): Foo = FooImpl()
【返回值类型】
关键字 | 说明 |
Unit | 返回值无类型。不显示声明返回值类型都会返回Unit类型,类似Java中void用法 |
Nothing | 没有返回值。函数不return会执行失败(抛异常),异常就是 Nothing 类型 |
Any | 所有类型的父类。提供了 equals()、hashCode()、toString() |
//没有返回值类型返回的是Unit,可不写
fun show(name: String): Unit { print("...") } //fun show(name: String) { print("...") }
fun fail(message:String):Nothing{
throw IllegalStateException(message)
}
public inline fun TODO(reason: String) : Nothing = throw NotImplementedError("An operation is not implemented :$reason")
【默认参数值】(函数重载)
可以预先给参数指定默认值(缺省值),不必像 Java 那样写一大串重载函数。
fun getStudent(age: Int, sex: String = woman){
println("年龄:$age,性别:$sex")
}
getStudent(18, man) //打印:年龄:18,性别man,传入会覆盖默认值
getStudent(20) //打印:年龄:20,性别woman,不传入使用默认值
上面函数在Java中调用只相当于提供了:
void getStudent(int age,String name){}
如果过想在Java中也当作重载函数使用,需要使用 @JvmOverloads 注解来修饰函数,同样适用于构造函数和静态函数。而如果一个函数不想被Java调用 则使用 @JvmSynthetic。
@JvmOverloads
fun getStudent(age: Int, sex: String = woman){
println("年龄:$age,性别:$sex")
}
上面函数在Java中调用相当于提供了:
void getStudent(int age){}
void getStudent(int age,String name){}
【具名参数】(命名参数)
在传递参数的时候,指定参数的名称。这样做的好处就是可以不必按照参数的顺序去传值,参数特别多的时候,它们都很像容易传错。(一旦其中有一个参数使用了命名传参,它前面的不用管(当然是按照参数列表顺序赋值的不然报错),它后面的所有参数都要使用命名传参)。
fun getStudent(name: String, age: Int) {
println("姓名$name,年龄$age")
}
getStudent(age = 10, name = "张三") //打印:姓名张三,年龄10
【单表达式函数】
函数返回单个表达式时,返回值类型自动推断可以不写,可以省略 return 使用 = 赋值为表达式结果。
//返回值类型可以不写,自动推断
fun getNum(x:Int, y:Int) = x + y
fun getName(name: String) = println("名字是:$name")
//可以直接 return 表达式的结果
fun generateAnswerString(countThreshold: Int): String {
return if (count > countThreshold) {
"I have the answer."
} else {
"The answer eludes me."
}
}
//还可以将 return 关键字替换为赋值运算符
fun generateAnswerString(countThreshold: Int): String = if (count > countThreshold) {
"I have the answer"
} else {
"The answer eludes me"
}
【可变参数】(变长参数)
函数的参数数量不确定,Java 通过三个点表示(String...str),Kotlin 通过关键字 vararg 修饰,表示该类型的数量可变,通常应该把它放在参数列表的最后一个。
//Java
void method(String name, Int...scores){}
//Kotlin
fun method(name: String, vararg scores: Int) {
var scoreString = scores.joinToString(",") //可变参数在函数体中自动变为数组类型使用
println("姓名:$name, 得分:$scoreString")
}
//使用
val scores = intArrayOf(5,1,6,4)
//Kotlin中需要使用展开运算符 *, 表示将数组中的元素逐个传入到变长参数中(Java可直接传数组)
method("张三",*scores) //打印: 姓名:张三, 得分:5,1,6,4
【参数泛型】
更详细介绍参见这篇笔记《Kotlin - < >泛型》
fun <T> show(t: T){ return t}
【反引号中的函数名】
- 解决关键字冲突:Kotlin 和 Java 各自有不同的保留关键字
- 强行将一个不合法名称变得合法:做测试的时候也能使用空格和特殊符号命名函数(空格无法用于 Android 项目)
//使用特殊符号和空格
fun `**This is a test for function Show()**`(){
println("哈哈哈")
}
//使用数字开头命名
fun `123`(){}
//Kotlin调用Java中名称为is()的函数
MyJava.`is`()
【局部函数】(内部函数)
函数内部也可以定义函数。局部函数可以直接访问外部函数的局部变量、常量。
fun outer(){
val a = 3
val b = 3
fun inner(){
println("结果是: + $a + $b")
}
}
【成员函数】(方法)
方法和函数几乎一模一样,唯一的区别是必须声明在类里面。方法必须通过类的实例调用,每个方法可以在方法内部拿到这个方法的实例。
fun eat() = Unit //函数
class Person{
fun eat() = Unit //方法
}
【空函数】
强制要求重载但又不需要使用的函数
override fun aaa(a: Int) = Unit