Kotlin从入门到精通(抛弃)一
一.Kotlin的非空校验
在Kotlin中,不允许声明的变量为null,而且它并不像java相同给变量赋了默认值。所以假如你声明了一个未赋值的变量,他就会提示你属性必须初始化或许笼统,或许增加一个推迟初始化,像下图相同:
所以,假如咱们想声明一个未初始化的变量,咱们有下面几种方式来声明。
1. 经过可空类型来声明变量
咱们在声明变量的时分,在变量类型后边加个?,来赋值为null,这样就可认为变量赋空了,像这样:
var str:String?=null;
咱们就可认为str赋一个空了,可是咱们在运用的这个变量的时分,又会 呈现以下状况
根据提示,咱们也能够看出来,说的是一个可为空的变量不能直接运用,那咱们怎样运用这个变量str呢? 一般的也有三个办法:
- 运用空判别
这个很简单,便是运用变量时,在变量后边增加?.也便是str?.length就能够运用可为空变量了,加这个之后,当变量为空时,就不会履行字符串调用的函数,也便是str为空时,就不会履行str.length这个函数
- 运用非空断语
这个便是比较刚性,假如str确实为空,会抛一个反常的,不推荐。。。
- 结合规范函数运用
这个比较常用,一般是和规范函数let结合空操作符:?来运用,比如上面的str字符串,咱们运用
var str: String? = null var str1 = str?.let { str.capitalize() } ?: "abc" println(str1)
这个代码是什么意思呢,str?.let便是来判空的,假如为空,就不走进这个lambda表达式,然后?:便是空操作符,也便是str为null的话,会给他一个默认值”abc”,这儿咱们需求留意的是,规范库let函数返回值lambda表达式的最终相同,由于let函数中声明的lambda表达式是block:(T)->R,而且返回的是block(this),所以调用的时分T其实便是其时目标,其时是val类型的,也便是java中的final类型,咱们并不能改变它的指向,所以咱们用str1来接纳lambda表达式中返回值。所以str1和str并不相同。结果是这样,可是分析进程不一定对。。。
2. 经过延时初始化关键字来声明
像下面这样声明,就能够运用未初始化的变量了,可是下面的代码运用时,假如未赋值,就会报空指针反常哟。
lateinit var string:String string.capitalize()
小结
Kotlin在声明变量时,假如未赋值,它并不会像java相同会给个默认值,所以不允许咱们调用未赋值的变量,假如咱们想自己拿回自动权,一般能够经过可空变量?和推迟初始化关键字lateinit,可是这个也会代码在履行的时分可能抛空指针反常,这个呢,就需求咱们自己在代码里边处理了,像能够经过可空判别?.、非空断语!!以及规范库函数?.let来自动处理,防止空指针反常。
二.Kotlin中的函数
1. 规范的函数
- 能够指定参数,这样就省去了函数的重载
- 办法中能够给临时变量设置默认值
- 能够在声明函数时,用等于号给函数赋默认值
举个例子:
fun funCommon(str: String, i: Int = 12): String { return str; }
像上面声明一个函数,形参i,咱们能够给默认值,咱们在调用时,能够具名形参(省去了重载),像这样funCommon(str = "abc", i = 16)
或funCommon(str = "abc")
来调用
2. 匿名函数
- 常规的匿名函数
- 类型揣度的匿名函数
- 运用inline防止lambda目标的重复创立
- 匿名函数的写法
什么是匿名函数?匿名函数便是没有姓名的函数,咱们一般是经过以下过程来给匿名函数界说: 1.声明一个函数变量用来接纳匿名函数; 2.用lambda表示函数参数以及返回值,能够省去 形参声明的变量,也便是i:Int能够直接替换成Int作为形参声明; 3.={}为lambda表达式赋值;4.lambda表达式的最终一行是匿名函数的返回值。
- 常规写法及揣度类型写法
举个例子,咱们界说一个匿名函数
var funAnonymous: (Int) -> String = { it.toString() }
,咱们分析下这个函数,它是个函数变量名为funAnonymous,它是一个入参为Int类型,这儿面咱们省掉了形参变量名编写,返回值为String类型的函数,函数体的内容为大框号里边的内容,由于只要一个参数所以it代表了入参的变量,它的返回值即代码的最终一行。上面仅仅一个单个参数的,当多个参数时,咱们需求界说多个参数来接纳入参,像var funAnonymous5: (Int, String) -> String = { _i, _s -> _i.toString() + _s }
这样在大框号中界说接纳或var funAnonymous4: (_i: Int, _s: String) -> String = { _i, _s -> _i.toString() + _s }
这样在入参的时分声明下类型都能够。 其实咱们也能够省去中间入参和返回值的代码编写,由于Kotlin具有类型揣度的才能,所以var funAnonymous: (Int) -> String = { it.toString() }
能够写成var funAnonymous = { it.toString() }
,这样看上去像是一个代码块,可是在Kotlin中,它的确是个函数!相似的还有funAnonymous4还能够这样界说,var funAnonymous4 = { _i, _s -> _i.toString() + _s }
这个也是省去了形参和返回值,直接类型揣度的写法。
3.高阶函数与inline关键字以及闭包的概念
- 高阶函数的概念和写法
什么是高阶函数?听上去如同很厉害的样子,你用java的了解便是办法的参数是一个匿名目标,或许假如你玩过C或许C++就一定知道函数指针的概念,形参便是一个函数指针相似这样的概念。
举个例子说吧
fun funSenior(str:String,param:(String)->String):String{ return param(str) }
这个便是一个高阶函数,函数的参数是一个匿名函数,那么,咱们怎样调用呢,咱们来界说一个匿名函数param:var param={ str:String-> "$str abc" }
然后咱们来调用这个高阶函数funSenior("abc", param)
- 闭包的写法和作用
留意,咱们在funSenior这个高阶函数中运用到了闭包,那什么是闭包呢,依照java的了解,办法都是压栈的,办法中的变量跟着办法的履行完毕变量生命周期就完毕了,这儿咱们在funSenior的第一个参数str作为funSenior的另一个参数匿名函数的参数,像这样被界说的函数(param)能够访问界说其的函数(senior)声明的变量(str),就形成了闭包,闭包主要是处理脚本言语没有包的概念,防止同名变量的问题。需求留意的是,咱们能够这样去调用这个高阶函数
funSenior("12"){ "$it abc" }
当然,这样写是有前提的,只要当最终一个参数是lambda表达式或许只要一个匿名函数参数。
- 内联关键字
虽然lambda很好用,可是它也有坏处,jvm会为每个lambda表达式创立一个目标,调用完后又回去销毁,那inline便是为了防止目标的创立,它有点相似于C中的宏界说,当你在调用lambda表达式的函数时,它就不会直接创立目标,编译器直接将函数赋值粘贴过去,就拿上面的高阶函数的调用来说,咱们没加inline前,反编译的源码是这样的
funSenior("12", (Function1)null.INSTANCE);
,加了inline之后(new StringBuilder()).append(str$iv).append(" ABC").toString();
能够看出来,运用inline之后,代码更多了,可是并没有创立Function1目标,这样就防止了目标的重复创立。
- 函数引证
对了还有个关于函数的知识点,便是将函数的引证作为参数,相似于这样的写法:
/** * 函数引证作为参数 */ funSenior("123", ::param1); } fun param1(str: String): String { return str; } fun funSenior(str:String,param:(String)->String):String{ return param(str) }
,怎样了解这样的写法呢,你能够用C中的函数指针或许java中的目标的办法去了解它,其实它本身便是一个函数目标,而且在运用lambda表达式的当地都能够运用函数使用,额,对了,在java8中如同也能够用这样的写法。
4. 结构函数
这个其实没有什么好说的,需求记住的便是它的履行顺序,主结构->属性->init代码块->次结构函数,所以留意调用的时序哟。
小结
Kotlin能够说是函数式编程,而且依靠强壮的lambda表达式和类型揣度大大简化了代码量,可是它也有坏处,所以运用了inline关键字,而且相似于脚本言语,它也有闭包的概念,相同它又有点像C言语那样能够将函数目标(引证)作为参数,总之,了解了kotlin的函数式编程,基本上就能够看懂他人的Kotlin小项目。码字不易,假如觉得此文对你有用,欢迎动动小手沟通沟通。