Kotlin的显式类型声明是:java
val sum = { x: Int, y: Int -> x + y }
val action = { println(42) }
// 有两个Int型参数和Int型返回值的函数
val sum: (Int, Int) -> { x, y -> x + y }
// 没有参数和返回值的函数
val action(): -> Unit = { println(42) }
复制代码
声明函数类型,须要将函数参数类型放在括号中,紧接着是一个箭头和函数的返回类型,以下:markdown
(Int, String) -> Unit
|- 参数类型 -| |- 返回类型 -|
复制代码
Unit
类型用于表示函数不返回任何有用的值。在声明一个普通的函数时,Unit类型的返回值是能够省略的,可是一个函数类型声明老是须要一个**显式
的返回类型**,因此在这种场景下**Unit
是不能省略**的。app
函数类型的返回值是可空类型
& 函数自己可空
ide
var canReturnNull: (Int?, Int?) -> Int? = { x, y ->
y?.let {
x?.plus(it)
}
}
//测试
println(canReturnNull(1, 2))
println(canReturnNull(null, 2))
//输出结果
3
null
复制代码
var funOrNull: ((Int, Int) -> Int) ? = null
//测试
println(funOrNull?.let { it(1, 2) })
//输出结果
null
复制代码
**注意:**若是省略了括号,声明的将会是一个返回值可空的函数类型,而不是一个可空的函数类型的变量.函数
注意该函数自己可空时调用须要使用**
?
类型**测试
// 定义一个函数类型的参数:operation
fun twoAndThree(operation: (Int, Int) -> Int) {
// 调用函数类型的参数
val result = operation(2, 3)
println("The result is $result")
}
fun twoAndThreeTest() {
twoAndThree{ a, b -> a + b }
twoAndThree{ a, b -> a * b }
}
// 输出结果
The result is 5
The result is 6
复制代码
调用做为参数的函数和调用普通函数的语法是同样的:把括号放在函数名后
,并把参数放在括号内
。ui
函数声明的示意图1: spa
filter
函数以一个判断式做为参数。判断式的类型是一个函数,以字符
做为参数
并返回boolean类型
的值。若是要让传递给判断式的字符出如今最终返回的字符串中,判断式须要返回true,反之返回false。code
fun String.filter(predicate: (Char) -> Boolean): String {
val result = StringBuilder()
for(index in 0 until length) {
val element = get(index)
// 调用做为参数传递给“predicate”的函数
if(predicate(element)) result.append(element)
}
return result.toString()
}
fun stringFilterTest() {
// 传递一个lambda做为“predicate”参数
println("abcABC123".filter {
it in 'a' .. 'z'
})
}
// 输出结果
abc
复制代码
函数类型被声明为普通的接口:一个函数类型的变量时FunctionN接口的一个实现。Kotlin标准库定义了一系列的接口,这些接口对应于不一样参数树立的函数:Function0(没有参数的函数)、Function1<P1, R>(一个参数的函数),等等。每一个接口定义了一个invoke方法,调用这个方法就会执行函数。orm
一个函数类型的变量就是实现了对应的**FunctionN
接口的实现类的实例**,实现类的**invoke
**方法包含了lambda函数体。
/* kotlin 声明 */
fun processTheAnswer(f: (Int) -> Int) {
println(f(42))
}
/* Java */
// 调用processTheAnswer方法
// 在Java代码中使用函数类型(Java8之前)
public static void processTheAnswerTest() {
processTheAnswer(
new Function1<Integer, Integer>() {
@Override
public Integer invoke(Integer number) {
System.out.println(number);
return number + 1;
}
}
);
}
// Java 8
processTheAnswer(number -> number + 1)
复制代码
在Java中能够很容易地使用Kotlin标准库中以lambda做为参数的扩展函数。
可是要注意:必需要显式地传递一个接受者对象做为第一个参数:
public void printString() {
List<String> strings = new ArrayList<>();
strings.add("42");
// 能够在Java代码中使用Kotlin标准库中的函数
CollectionsKt.forEach(strings, s -> {
System.out.println(s);
// 必需要显式地返回一个Unit类型的值
return Unit.INSTANCE;
});
}
复制代码
在**Java
中,函数或者lambda能够返回Unit
。但由于在Kotlin中Unit类型是有一个值的,因此须要显式地返回**它。
注意:一个返回
void
的lambda
不能做为返回Unit的函数类型的实参! 就像以前的例子中的(String) -> Unit
enum class Delivery { STANDARD, EXPEDITED }
class Order(val itemCount: Int)
fun getShippingCostCalculator( // 声明一个返回函数的函数 delivery: Delivery): (Order) -> Double {
if(delivery == Delivery.EXPEDITED) {
// 返回lambda
return { order -> 6 + 2.1 * order.itemCount }
}
// 返回lambda
return { order -> 1.2 * order.itemCount }
}
fun getShippingCostCalculatorTest() {
// 将返回的函数保存在变量中
val calculator =
getShippingCostCalculator(Delivery.EXPEDITED)
// 调用返回的函数
println("Shipping costs ${calculator(Order(3))}")
}
// 输出结果
Shipping costs 12.3
复制代码
声明一个返回另外一个函数的函数,须要指定一个函数类型做为返回类型。
在上述代码中,getShippingCostCalculator返回了一个函数,这个函数以Order做为参数并返回一个Double类型的值。
要返回一个函数,须要写一个return表达式,跟上一个lambda、一个成员引用,或者其余的函数类型的表达式,好比一个(函数类型的)局部变量。