Kotlin函数由易到难

函数的使用

kotlin 复制代码
//1.Unit相当于java的Void 返回值,如果没有返回就可以不写
fun test(): Unit{
}

//2.带参数的函数,返回为Int类型
fun test(a: Int, b: Int): Int{
	return a + b
}
fun test(a: Int,b: Int): Int = a + b //可以简写去掉"{} "用"="代替
fun test(a: Int,b: Int) = a + b //已知返回类型为Int,也可以省略Int

//3.参数设置默认值
fun test(a: Int = 6, b: Int = 10): Int{
	return a + b
}

注意:函数的形式参数默认情况下为常量,无法进行修改,如下截图

kotlin 复制代码
//4.函数内部也可以定义函数
	fun test(){
		fun inner(){
		//函数内部定义的函数,无限套娃
		}
		inner()//函数内的函数作用域是受限的,我们只能在函数内部使用
}

再谈变量

kotlin 复制代码
//1.顶级定义,直接写在Kt文件中,这个变量可以被所有的函数使用
var a: Int = a 
fun main() = Println(a)
fun test() = println(a)

以上也只是对变量的一些简单使用,现在变量的作用域被提升到顶层,它可以具有更多的一些特性,那么,我们就再来重写认识一下变量,声明一个变量的完整语法如下:

kotlin 复制代码
var <propertyName>[: <PropertyType>][= <property_initializer>]
    [<getter>]
    [<setter>]

对于变量的获取和设定,本质上都是通过其getter和setter函数来完成的,只不过默认情况下不需要我们去编写。

编译之后:

这是为了后续多态的一些性质而设计的。

kotlin 复制代码
//2.get函数,field 就是这个变量a
var a: Int = 5
    get() = field * 10
fun main(){
	println(a)
}
//打印结果:50

//3.set函数,重新给变量a 赋值,就是通过set函数
var a: Int = 5
    set(value){
    	field = value * 10
    }
fun main(){
	a = 90
	println(a)
}
//打印结果:900

递归函数

kotlin 复制代码
fun main(){
println(test(5)) //计算0-5的和
}
//这个函数实现了计算0-n的和的功能
fun test(n: Int): Int{
	if(n == 0) return 0   //当n等于0的时候就不再向下,而是直接返回0
	return n + test(n - 1) //n不为0就返回当前的n 加上test参数n-1的和
}
//5+ test(4) = 5 + 4 + teset(3) = 5 + 4 + 3 + test(3) = ....5 + 4 + 3 + 2 + 1 + 0

对于函数递归来说,这种方式效率低下,所以使用关键字 tailrec来优化上面的求和的函数,其原理是使用了while循环。

斐波那契数列的优化为:

函数类型的变量

kotlin 复制代码
//1.表示一个接收String作为参数返回值为Int的函数类型,如果返回类型不明确要写成Unit并且不可以省略。
var func:(String) -> Int

//2.方法的引用"::"
fun main(){
var func: (String) -> Int = ::test
println(func(""))
}
fun test (str: String): Int{
	return 666
}
//打印结果:666

//3.也可以写出匿名函数,没有函数名
var func: (String) -> Int = fun(str: String): Int{
		return 10
}
println(func(""))

//简化写法 var func:(String) -> Int = fun(str:String) = 10

//打印结果10

lambda表达式与高阶函数

kotlin 复制代码
//1.函数类型的变量匿名函数的方式可以使用lambda表达式{}来表示
fun main(){
var func: (String) -> Int = {
	println(it) //it代表传入的参数
	10
}
	func("Hello World")
}
//打印结果:Hello World

//2.两个参数,需要定义两个参数
fun main(){
var func: (String,String) -> Int = {a,b ->
	println(a)
	println(b)
	10
}
var func2: (String,String) -> Int = {_,b ->
	println(b) //假如这里不使用第一个参数,也可以使用_下划线来表示不使用
	10
}
	func("Hello World","haha")
}
/*
打印结果:
Hello World
haha
*/

函数传入的参数是函数就称为高阶函数,最直接的方式就是下面这样:

kotlin 复制代码
fun main(){
	val func: (String) -> Int = {10}
	test(func)
}
fun test(func: (String) -> Int){
	println(func("Hello World"))
}

//还可以这样写,传入一个lambda表达式
fun main(){
	test({
		println(it)
		20
	})
}
fun test(func: (String) -> Int){
	println(func("Hello World"))
}
/*
打印结果:
Hello World
20
*/

不过这样写还不够简洁,在Kotlin中,如果函数的最后一个形参是一个函数类型

,可以直接写在括号后面,就像下面这样:

kotlin 复制代码
test(){
		println(it)
		20
	}

由于小括号里面此时没有其他参数了,还可以继续省略,直接把小括号干掉:

kotlin 复制代码
test{
		println(it)
		20
	}

当然,如果在这之前有其他的参数,只能写成这样了:

kotlin 复制代码
test(10){
		println(it)
		20
	}
//这里两个参数,前面还有一个int类型参数,但是同意的最后一个参数是函数类型
fun test(a: Int,func: (String) -> Int){
	println(func("Hello World"))
}	

在Lambda中没有办法直接使用return语句返回,需要使用标签。

函数调用的是尾随lambda表达式

内联函数

添加关键字inline

kotlin 复制代码
fun main(){
	test()
}
inline fun test(){
	println("这是一个内联函数")
}

内联函数在编译的时候会把函数里面的内容直接放到调用的地方,可以查看编译后的class文件。

如:

kotlin 复制代码
fun main(){
	println("这是一个内联函数")
}

高阶函数也是一样的,如下:

有两个注意点:

1.内联函数中的形参不能作为值给到变量,除非在func前面加上"oninline"来修饰

2.内联高阶函数的Lambda参数可以直接写return,不指定标签

但是如果不指定标签返回的话就有问题了,会直接返回全局,不符合逻辑

kotlin 复制代码
fun main(){
test{ return }//内联高阶函数的Lambda参数可以直接写return指定标签
println("调用上面方法之后")
}
inline fun test(func: (String)-> Unit){
	func("HelloWorld")
	println("调用内联函数之后")
}
//打印结果:没有任何打印


//需要返回什么,打上标签,如返回test内联函数,如下:
fun main(){
test{ return@test }//这样就只会使test返回,而不会影响到外部函数了
println("调用上面方法之后")
}
inline fun test(func: (String)-> Unit){
	func("HelloWorld")
	println("调用内联函数之后")
}
/*打印结果:
调用内联函数之后
调用上面方法之后
*/

加上noinline关键字的使用:

相关推荐
快意咖啡~1 分钟前
java.nio.charset.MalformedInputException: Input length = 1
java·开发语言·nio
李钢蛋5 分钟前
PHP函数---function_exists()详解
开发语言·php
Joyner20186 分钟前
pytorch训练的双卡,一个显卡占有20GB,另一个卡占有8GB,怎么均衡?
人工智能·pytorch·python
halo141610 分钟前
uni-app 界面TabBar中间大图标设置的两种方法
开发语言·javascript·uni-app
froginwe1119 分钟前
Go 语言数组
开发语言
瑞雨溪19 分钟前
python中的OS模块的基本使用
开发语言·python
醒过来摸鱼24 分钟前
【Golang】协程
开发语言·后端·golang
时光追逐者25 分钟前
.NET 9 中 LINQ 新增功能实操
开发语言·开源·c#·.net·.netcore·linq·微软技术
Leuanghing26 分钟前
使用Python生成F分布表并导出为Excel文件
开发语言·python·excel·f分布
IT枫斗者28 分钟前
如何解决Java EasyExcel 导出报内存溢出
java·服务器·开发语言·网络·分布式·物联网