粉丝160获赞340

大家好,我是人物线朱凯,我回来了,我也不知道为什么我要摆这个动作。在上一期里,我介绍了一下漂亮的携程到底是什么东西,他就是个县城框架,没有什么说不清楚的,他就是个县城框架,只不过这个县城框架更方便一点。 另外呢,上期还讲了一下携程基本用法,但到最后也留下了一个大问号,就是携程的这个所谓的最著名的挂起是个什么东西,对吧?这期我们核心内容就是去说一下这个挂起。首先,这个挂起是挂起谁呢?挂起鲜橙,挂起函数, 都不是,挂起的是携程。还记得携程是什么吗?上期讲过的携程就是 launch 里的那些代码,而其实除了 launch, 还有一个创业携程的喊出,叫做 i think。 不过我在视频里就不介绍了,你可以去看我们的文章, launch 创建这个携携程在执行的某一个 spa 函数。挂起函数的时候,这个携程会被 span 被挂起。 从哪挂起?从当前县城挂起,说白了就是这个携程从正在执行他的县城上脱离了。注意,不是这个携程停下来了,虽然在这边有暂停的意思,而是什么呢?而是这个携程所在的县城,从这一行代码开始不再运行这个携程了。 那么到现在开始,我们就需要缤纷两路去分别,看一看这两个分离了的县城和携程各自将发生什么。 首先,这个县城他和携程分离了,具体的代码是什么意思呢?携程的代码块在县城里,到了 cc 的函数的时候,突然执行完毕了,返回了。完毕之后县城干嘛呢?他也干嘛干嘛去? 如果这个县城是一个后台县城,那么接下来他可能就没事干了,或者去执行别的后台扔,总之跟嘉巴的县城之力,那县城在做完事之后是一样的,要么回收掉,要么再利用。 而如果这个县城是艾瑞的主县城,那么他接下来就会回去继续工作。什么叫回去继续工作?首先,如果你启动一个执行在主县城的携程,他实质上会往你的主县城 pose 的一个新任务,这个任务就是你的携程代码, 那么当这个携程被挂起的时候,实质上就是你 pose 这个任务提前结束了,那这时候主角想干嘛?想想现在他该干嘛?继续刷新见面呗,对吧?就是这样。那,呃,剩下的代码怎么办?携程不是还没执行完 吗?刚才我说什么兵分两路对吧?看完县城,我们就来看一下县城和携程分离了之后,携程发生了什么。 函数的代码在到达挂起函数的时候被掐断了,所以接下来他会从这个挂起函数开始继续往下执行,不过是在指定的县城,谁指定的挂起函数指定的?比如我们这个例子里,就是函数内部的那个 with context 所指定的 i o 县城。 另外,在挂起函数之前完成之后,携程为我们做的最爽的事就来了,他会自动帮我们把建成再切回来。 比如如果我的携程原本是在主线程就行的,那么这个所谓的切回来就是在挂起函数执行完成之后,携程会帮我再 pose 一个任务,让我剩下的干嘛继续 回到主线城去执行。这就是为什么你指定县城那个参数不叫 threads, 而是叫 dispatches, 叫度气。他不只能指定携程执行的县城,还能在 suspense 挂起函数之后自动再切回来 啊。其实也不是一定会切回来,你也可以通过设置特殊的 space, 再让挂起函数执行完之后也不切回来。不过这是你的选择,而不是他的定位, 挂起的定位就是暂时接走,稍后再切回来。好到这终于可以对携程呢挂起做一个解释了。携程在执行呢,有 sisspen 标记了函数,也就是挂起函数的时候,他会被斯斯顿,也就是被挂起。 而所谓的挂起,其实跟开启一个切成一样,说起来比较玄悟,但其实就是切割现成。只不过 挂起函数在执行完毕之后,携程会自动的重新切回他原先的那个县城,所以所谓的挂起,其实就是一个稍后会被自动切回来的县城切换 住院。说一下,那个切回来的动作在携程里面叫做 resume 恢复。那么回到上期最后那个问题,为什么挂起函数只能在携程里或者另一个挂起函数里面被调用?首先挂起之后是需要恢复的,也就是把现成给切回来, 对吧?而恢复这个功能他是携程的,所以如果你一个挂起函数不在携程里面被被调用,那么这个恢复的功能就没法实现,是吧?另外你想一下这个逻辑啊,如果一个挂起函数,他要么在携程里面被调用, 要么在另一个挂起函数里面被调用,那么是不是实质上他不管是直接还是间接的,他总是终归还是要在一个携程里面被调用的,对吧? 所以说要求一个挂起函数必须要么在携程里面被吊用,要么在另一个挂起函数里面被吊用,他终归还是为了什么?为了让携程能够在挂起函数切换现成之后再切回来。 说完了挂起是什么,现在我们就接着再顺着去看一看这个挂起是怎么做到的。 首先你可以试着自定义一个挂起函数,然后在主线成长的携程里去调用它,你会发现他还是运行在主线城,没有切换。为什么没切?因为他不知道往哪切呀,你又没 告诉他往哪切,他怎么切?你看我们之前例子里面那个自定义的挂切函数,他里面是有一个 v context, 对吧? 而且这个 with context 他也是一个挂起函数,他接受了一个 despatch 参数,然后有了这个 despatch 参数,你的 with context 才知道往哪儿切,接着你的携程才被挂起了,也就是切到别的县城去了, 是吧?也就是说,所谓的携程被挂起或者说切现成这件事情,它并不是发生在你外部这个挂起函数被调用的时候,而是里面那个挂起函数,那个 wet contact 被调用的时候。 当然了,如果你再往代码里面去钻一下,你肯定也会发现这个 vipex 其实也不是真正切现成的点,而是他内部某一行代码。不过这个不重要了,因为我要说的是,所以 这个斯斯文关键字,他其实并不起到任何的把携程挂起或者说切换现成的作用。 真正要挂起携程,还需要你在挂起函数里面去调用另外一个挂起函数,而且里面这个挂起函数他需要是携程自带的,内部实现了携程挂起代码的, 或者他不是自带的,但他的内部直接或者间接的调用了某一个自带的挂旗函数,那也行。总之你最终需要调用到一个自带的挂旗函数,让他来去真正的做挂旗,也就是现场切换的工作。 所有的挂旗函数不只为看在第一个,还有别的他们都能实现携程的挂旗。而我们要想自己写一个自定义的挂旗函数,就需要在这个挂旗 喊出内部直接或者间接的去叼,用到某一个自带的挂旗喊出那才行。只加这个关键字,加上这个 s spin 是不行的,这关键字没有那么神奇,这么讲应该好理解吧。那么到这里,其实另一个问题就来了,这个 spin 关键字既然它不能真正实现挂旗, 那他的作用是什么呢?这是一个看起来学术,但其实非常实际,对写代码非常有帮助的问题。 我知道有的人已经研读过卡顿携程的代码,知道了变异器是怎么实现了,携程,也知道卡顿是怎么实现挂起的。但今天我们抛开这些底层实现的问题,我们就看语法,在语法上这个奇思,变关键字他到底是什么作用? 具体想说啊,他们为什么会给我提供这个关键字让我用呢?你看咱刚讲过,他对于携程 的话题并没有任何的实质作用,对吧?那他到底是干嘛的呢?或者说为什么这关键字不干脆就直接删掉呢?注意听了,不管你是阿里的,腾讯的啊,头条的,哥哥的, facebook 的,现在我要讲的东西都非常有用。 cc 半关键字的作用是什么?它其实是一个提醒, 谁对谁的提醒。函数的创建者,对函数的调用者的提醒。我是一个耗时函数,因此我为我的创建者用挂起的方式放在了后台运行,所以请在携程里调用我。 表面上他是一个要求,你需要在携程里教育我,但本质上他其实是一个提醒。提醒什么?我是一个被自动放在后台运行的耗时函数,所以你需要在携程里教育我, 明白了吧?这才是资本。关键字的作用,他是一个提醒,提醒调动者我耗时,那么这个提醒他又有什么用呢?这个提醒他能让我们的主线成不卡? 你想我们的小家伙的时候,在主线上做事需要非常小心,对吧?一旦你不留神,在主线上掉了一个耗时方法,那这就会卡一下, 是吧?而且这种事是很难避免的,因为我又不知道哪个方法会耗时,对吧?又不是我写的, 而且就算是我写的,万一我忘了呢?而携程通过挂起函数这种形式,他把耗时任务切线成这个工作实际上交给了函数的创建者,而不是调用者,对吧?对于调用者来说,事情非常简单,他只会收到一个提醒,你需要把我放在 写成里面,剩下的其他他都不用管。而通过这种方式次次办这关键字,他实际上作为一个提醒,是形成了一种机制,一种让所有耗时任务全都自动放在后台执行的机制。那么主线长是不是就不卡了? 所以为什么这个关键字他并没有实际去操作挂旗,但是高冷却给我们提供出来让我们用?因为他的定位就不是用来去操作挂旗的。 挂起操作靠的是挂起函数里面的实际代码,而不是这个关键字。实际上你试一下,如果你创建一个挂体函数,但却不在他内部,要用别的挂起函数, ange studio 会给你一个提醒,告诉你这个 span 是多余的。 为什么多余?因为你这个函数实际上并没有发生挂机,那你这个资本关键字就只有一个效果,那就 限制这个函数只能在携程里被吊用,那这肯定没必要啊,对吧?你又不去挂机携程,为什么还要限制在携程里才能吊用呢? 所以说,你创建一个挂起函数,一定要在他内部要用别的挂起函数,你的这个挂起才能是有意义的。 那么再了解了挂起到底是什么,此反对关键字到底有什么意义之后,我们就可以进入下一个话题了。怎么制定一个挂起函数?这个话题如果你不知道前面我说那些,直接进入这一步,你会头晕呕吐的。 这个怎么自定义?其实可以分为两个问题,什么时候需要自定义,以及写的时候怎么写。首先,什么时候自定义这个问题可能很多人觉得太虚无了,不好回答,但其实答案很简单,如果你的某个函数比较 耗时,那就把它写成挂起函数,这就是原则。那什么会比较耗时呢?一般就两类, io 操作和计算工作,比如文件的读写、网络交互、图片的模糊或者美化处理,都是耗时的,通通可以把它们写进挂起函处理。 另外这个耗时还有一种特殊情况,就是这件事本身做起来并不慢,但他需要等待,比如五秒钟之后再做这个操作。这种也是挂起函数段应用常见。 另外就是写的时候怎么写呢?太简单了,给函数加上 s 四遍关键字,然后用 win contests 把函数的内容包住就可以了。不管是什么时候要写,还是具体怎么写,都是很简单的问题。那为什么大家觉得难?因为你的前置知识不够,你不知道什么是挂旗, 不知道 cc 本关键字有什么意义。那你怎么能想明白,怎么能做明白呢?对吧?有的人在这里可能会有问题了,哎,你不是说除了 vict context 还有别的挂起函数吗?为什么你说资金易挂起函数要用 vict context, 那别的不能用吗? 不是别的不能用,而是 vcantics 是最常用的,也是最适合用来上手的,因为它的功能最简单,也最直接,把线程切走再切回来。 别的挂解函数功能总会比他多一些或者少一些。比如有一个挂解函数叫做 delay, 他的作用是等待一段时间之后再去往下执行代码。那你能用他来写字另一挂解函数吗? 当然可以的呀,比如刚才我说的那种等待类型的耗时操作,就可以用定位来做,只不过你不用第一时间就去接触它,以及其他的那些 自带的挂旗夹住,你可以先把携程用的熟悉点了再说,不着急。好,这期内容就到这里。什么是挂旗?说一千到一万,其实跟携程一样都是切线程对吧?只不过是一种可以自动切回来的切线程。 在下一期里,我会详细的说一下挂起的那个非阻塞式是怎么回事,以及像携程和现在的关系这样。呃,一系列的比较常见的疑难问题, 面试官们可能会比较喜欢下一期,我说的对吧?另外呢,就是我在上一期的最后其实跟大家说过,非阻测是本来是要在这期讲的,对吧?那为什么挪到下一期了呢?主要是你看看进度条,都已经这么久了,我做一期视频很累的好吗? 啊,不过我也知道这个理由对于有些人来说是不够具有说服力的,所以我还准备了另外一个理由,这个理由就是,嗯,就是略略略。

如果你是一个使用 java 语言开发的后端程序员,那么这个视频能够让你五分钟之内学会 cotan, cotan 是谷歌制定的安卓应用的开发语言,嗯,那么它是基于 java 虚拟机去运行的,也就是基于 gbm 运行啊。我们 我们看一下 cotton 和加瓦的不同的地方,加瓦语言我们知道的文件都是一点加瓦结尾的, cotton 的原代码文件呢,它是一点 kt 结尾。 cotton 和加瓦类似的路口程序的话呢, 都是 man 方法。那么华登人的 man 方法的写法是这样的,犯关键字 man 清仓,然后冒号,然后数组类型,然后发型,发型里面是试卷类型,这个 man 方法或者 man 函数,整个在华等人变异之后,会把它转化成加瓦的 man 方法,他其实会最后会转化成这样的 一个加瓦的面板法,然后去执行 print 语句 print l n print, 它其实是在转化成加瓦使用的对应的加瓦的 cc 点点 alt 点 print 方法去执行的。那么定义变量对,而关键字变量名变量类型也可以不指点,那么不指点的话呢, 变音器会猜测这个变量的类型,如果不制定的话呢,那么不能够分成两步来复制,因为最近到第一步的时候呢,这个变音器无法知道它具体对应的是 类型。 v l 关键字定义产量相当于艾瓦语言里面的 final 类型的变量,那么这个 v l 定义的产量是不能够进行第二次复制的, 这个是不允许的。硬操作服务,咱们定义了一个数组,然后十是否在这个数组里面内心转换,内心转换的话呢,在宽特能里面是需要显示的去掉转换 函数进行转换的啊,和加瓦语言不同,并不会自行自动转换一幅语句,夸特人的一幅语句是可以作为一个结果值附给一个变量,不得直接输出 操作服重载加外语也是没有操作重载的,那么扣的呢,是可以对基本的操作服务进行重载,比如说加号,那么我们看到这个定义的,呃,两个类的类型, 类的话呢是 point, 那么这个就是类的定义的方法,类名两个侧边变量,然后这个十是默认值。这类里面写了一个操作符重载,操作符函数 加号,然后存在,对应的存在方法是两个 a 相加和两个 b 相加啊,这个类一旦定了一个加号的操作服存在之后呢?嗯,两个这种同类型相加的时候,就可以直接使用加号进行连接,这个加完的结果就是相当于执行这个方法结果。双引号里面可以写 两一堕落符号,开头三个简单的循环,循环的定义方法从一到五,循环,从五到一,从五到一,然后每次一减二,方法定义,我叫函数定义,犯关键字,函数名,参数名冒号,他说类型多个参数逗号隔开冒号返回制。扩展方法, 扩展方法指的是对嗯加瓦默认的类型,或者说叫加瓦内裤里面的基础类型进行扩展的一种方法,称之为扩展函数。比如看这个时区类型的一个扩展函数,一个函数名是可以自己随便定义, 那么这个函数定义好之后呢?我们的任意的一个词句类型都可以直接调用这个方法做处理,就类似于 默认的加法反派是一样的。每句类型的定义啊,多了一个克拉斯类关键字,每一句的变量不止。最后一就是变量限制服加法当中是 public private effort protect, 那么在 cotton 里面, 嗯, dfot 改成了这个 internal, 这个就是话筒能和加瓦语言不同的地方,还有一些不常见的一些使用方法就没有再细讲了,这个我们执行一下,看看我们能看到这个可以执行的。好了就到这里,感谢大家。

好,欢迎大家来到我们今天的安卓 vip 试听课,那么我们今天要跟大家讲的呃内容呢,是我们 angel cosin 携程实战的这样的一个系列课啊,那么我们今天要讲的这个内容呢?包括我们这些内容啊,比如说, 呃,我们都知道携程理解起来有难度,那么携程为什么学起来有难度是吧?携程是什么?还有在安卓当中,携程他用来解决什么问题? 还有携程和一步任务比较好,在哪里啊?携程的挂起与恢复啊,还有挂起与主色的区别,还有携程我们分为两部分啊,一个是基础设施,还有一个是官方框架, 那么携程的调度器,还有我们携程的结构化并发啊,这个是瑞士携程,那么携程上手呢?我们会用 呃,携程和我们的 retrofit view model, 还有我们的 life cycle 啊等等这些其他的这个主见啊,那么来,呃,带大家去做一个案例, 好,那么我们看到的呢,我们这个是呃,库特里携程实战的这样一个课程啊,这个,呃,这个完整的这个内容,他是这样子的,是吧?包括, 呃,我们刚讲的内容,包括我们学生的取消操作呀,异常处理啊,还有我们的热数据,冷数据流啊,啊,还有我们的项目加项目架构,这个,呃,搭建的这个实战啊, 啊,那么啊,你如果说想要了解这个课程的话呢,可以呃,扫码我们屏幕右下方的朱洁老师的微信,好吧,好,那么 呃,我是大家的老朋友啊,宁传奇啊,宁死不屈的宁传奇,故事的传奇,那么我们首先来看一下啊,携程他到底拦在哪里?

现在我就来教大家如何使用 cotton 来开发 android, 下面就来跟着我的视频来看我是如何操作的, 还是这么发给 一场光阴的雨, 如迷人的水晶般浪漫。风雨还是周末发给我。

那么携程啊,他到底是什么?那么我们肯定要去给他下一个定义,对吧?那么我们在这个地方呢,根据我们客厅这个官方的文档里面所提到的啊,我们, 呃在这个地方给他下了一个定义啊,就携程,哎,他是基于县城,那么他是轻量级的县城啊,所以呢,我们一开始就知道了啊,就是携程呢,他我们可以说是一个呃,新品装舅舅, 携程他没有脱离我们县城啊,在这个呃县城之上也有说呢,呃,比如说携程他是一个县城的框架 啊,那么这个定义呢,其实是比较狭隘的,为什么呢?如果说只是一个框架啊,比 就说我们的 x 加瓦,对吧? x 加瓦他其实是一个响应式编程的这样一个框架,呃,里面呢就会有很多多线层相关的这个操作。呃,但是我们往往谈到框架, 一般来说啊,框架其实是不太过分依赖于我们的编辑系的, 是不是?比如说我们的,呃,我们做安卓开发,那我们的 rachel feet 啊,我们各种各样的这个框架,还有我们比如说家瓦里面 surprine 等等这些啊。但是呢,携程 啊,这个他不只是简单的一个框架啊,他很多时候依赖于我们 cote 的这个语法特性,还有因为我们都知道 cote 他是一个变异性的语言啊。而 携程呢,他会借助于我们强大的科特林这个变异器啊,利用好我们这个变异器,他做了很多 啊,这个更高级的一些操作啊。所以否则如果说他只是一个现成的这样的一个框架,那为什么我不用 x 加网呢?对不对啊?所以呢,这个地方是要给大家去进一个解释啊?


听说 colin 可以用 lamda, 不错不错,加号吧也有 lamda, 挺好用的。听说 colin lamda 还能当函数参数,哎,挺好挺好,我也来写一个。哎,报错了我改, 哎,我再改我再改啊啊啊。大家好,我是人物线朱凯。干了很方便,但有时候也让人头疼,而且越方便的地方越让人头疼。 比如 lamda 表达是很多人因为 lamda 而被卡伦吸引,但很多人也因为 lamda 被卡伦吓跑。其实大多数已经用了很久卡伦的人对 lamda 也只会简单实用而已,甚至相当一部分人 不过开发工具的自动补全功能根本就完全不会写 lamd。 今天我就来跟大家唠一唠 lamd。 不过要讲 lamd, 我们得先从高阶函数 higher order function 说起。 在家务里,如果你有一个 a 方法需要调用另外一个 b 方法,你在里面调用就可以。而如果你想在 a 调用的时候去动态设置 b 方法的参数,你就得把参数传给 a, 再从 a 的内部把参数传给 b, 这都可以做到。不过,如果我想动态设置的不是方法的参数,而是方法本身呢?比如我在 a 的内部有一处对别的方法的调用,这个方法可能是 b, 可能是 c, 不一定是谁。我只知道我在这里有一个调用 他的参数类型是 int, 返回之类型是 void。 而具体在 a 执行的时候调用哪个方法,我希望可以动态设置,或者说,我想把方法作为参数传到另外一个方法里面,这个 可以实现吗?不行也行,在家法里是不允许把方法作为参数传递的。但是我们有一个历史悠久的变通方案皆可, 我们可以通过接口的方式来把方法包装起来,然后把这个接口的类型作为外部方法的参数。类型 在调用外部方法时,传递接口的对象来作为参数。如果到这里你觉得听晕了,我换个写法,你再感受一下。我们在用户发生点击行为的时候,会触发点击事件,所谓的点击事件最核心的内容就是调用内部的一个 uncooke 的方法, 而所谓这个 uncook listener 其实只是一个,可他的核心全在内部那个 oncook 方法。换句话说,我们传过来一个 oncook listener, 本质上其实是传过来一个可以稍后再被调用的方法 uncook, 只不过因为加法不允许传递方法,所以我们才把它包进了一个对象里来进行传递。而在干了里面,函数的参数也可以是函数类型的。当一个函数 含有函数类型的参数的时候,这句话有点绕啊,如果你要用它,你就可以当然念,必须传入一个函数类型的对象给他。不过在具体的写法上没有我的视力这么粗暴。首先,我写的这个范作为函数类型其实是错的, 他的你并没有这么一种类型来标记这个变量是个函数类型,因为函数类型不是一个类型,而是一类类型。 因为函数类型可以有各种各样不同的参数和返回值的类型的搭配,这些搭配属于不同的函数类型,例如无参数无返回值 和单印情参数返回 string 是两种不同的类型,这个很好理解,就好像 in 和 string 是两个不同的类型,所以不能只用 fan 这个词来表示这个参数是个函数类型。就好像不能用 class 这个词来表示这个参数是某个类, 因为你需要指定具体是哪种函数类型,或者说这个函数类型的参数,他的参数类型是什么,返回之类型是什么,而不能笼统的说一句他是函数类型就完了。所以对于函数类型的参数,你要指明他有几个参数,参数的类型是什么,以及返回之类型是什么,那么写下来就大概是这个样子, 看着有点可怕,但是只有这样写刁用的人才知道应该传一个怎样的函数类型的参数。同样的函数类型,不止可以作为函数的参数类型, 还可以作为函数的返回值类型。这种参数或者返回值为函数类型的函数,在干论里就被称为高阶函数 higher order。 放学这个所谓的高阶,总给人一种神秘感。阶是什么?哪里高了?其实没有那么复杂,高阶函数这个概念源自数学中的 高阶函数,在数学里,如果一个函数使用函数来作为他的参数或者结果,他就被称作是高阶函数。比如求导就是一个典型的例子,你对 fx 等于 x, 这个函数求导结果是一,对 fx 等于 x 平方,这个函数求导结果是二 x。 很明显,求导函数的参数和结果都是函数, 其中 fx 等于 x 的导数是一,这其实也是一个函数,只不过是一个结果横为一的函数,所以什么乱七八糟,总之,在缸里这种参数里有函数类型或者返回直视函数类型的函数都叫高级函数,这只是个对这一类函数的称呼,没有任何特殊性。高档的高级函数没有任何特殊功能, 这是我想说的。另外,除了作为函数的参数和返回值的类型,你把它复制给一个变量也是可以的。不过对于一个声明好的函数,不管是你要把它作为参数传递给函数,还是要把它复制给变量, 都得在韩束明的左边加上双冒号才行,这是为什么呢?如果你上网搜,你会发现这个双冒号的写法叫做函数引用方申 reference, 这个是高冷官方的说法,但是这又表示什么意思?表示他指向上面的函数。那既然都是一个东西,为什么不直接写韩束明而要加两个冒号呢? 因为加了两个冒号,这个函数才变成了一个对象。什么意思?在杠里,函数可以作为参数这件事的本质是函数可以作为对象存在,因为只有对象才可以被作为参数传递啊。复职也是一样的道理, 只有对象才能被副职给变亮啊。但干冷的函数的本身的性质又决定了他没办法被当做是一个对象。嗯,那怎么办呢?干冷的选择是,那就创建一个和函数具有相同功能的对象。怎么创建?使用双冒号,在缸里一个函数名的左边 加上双冒号,他就不表示这个函数本身了,而表示一个对象,或者说一个指向对象的引用。但这对象可不是函数本身,而是一个和这个函数具有相同功能的对象。怎么个相同法呢?你可以怎么用函数,就能怎么用这个加了双冒号的 对象?但我再说一遍这个双方号的东西,他不是一个函数,而是一个对象,一个函数类型的对象,对象是不能加括号来调用的, 对吧?但是函数类型的对象可以,为什么?因为这其实是个假的调用,他是卡朗的语法堂,实际上你对一个函数类型的对象加扣二加三数,他真正要用的是这个对象的 invo 函数。 所以你可以对一个函数类型的对象要用 invoke, 但不能对一个函数这么做。为什么?因为只有函数类型的对象有这个自带的 book 可以用,而函数不是函数类型的对象,那他是什么类型的?他什么类型?也不是函数不是对象,他也没有类型,函数就是函数,他跟对象是两个维度的东西, 包括双方号加上函数名的这个写法。他是一个指向对象的引用,但并不是指向函数本身,而是指向一个我们在代码里面看不见的对象。这对象他复制了原函数的功能,但他并不是原函数,这个是底层的逻辑。但我知道这个 有什么用呢?这个知识能帮你解开高冷的高阶函数,以及接下来我马上要讲的匿名函数和莱姆岛的大部分迷惑。比如我在代码里面有这么几行, 那如果我想把 d 复制给一个新的边量一,我等号右边的 d 是应该加双方号还是不加呢?不用试,也不用搜, 想一想,这个是个副职操作,对吧?副职操作的右边是个对象,对吧?第一是对象吗? 当然是了, b 不是对象,是因为他来自韩束明,但 d 已经是个对象了,所以直接写就行了。 我们继续讲,要传一个函数类型的参数,或者把一个函数类型的对象复制给变量。除了用双冒号来拿现成的函数使用,你还可以直接把这个函数挪过来写。另外,这种写法的话,函数的名字其实就没用了,所以你可以把它省掉, 这种写法叫做匿名函数。为什么叫匿名函数?很简单,因为他没有名字呗,对吧?等号左边的不是函数的名字啊,他是变量的名字。这个变量类型是一种函数类型,具体到我们的世界代码来说,是一种只有一个参数,参数类型是 inter, 并且 返回之类型为 string 的函数类型。另外呢,其实刚才那种左边右边都有名字的写法,看了是不允许的。右边的函数既然要名字也没用,看了干脆就不许他有名字。所以,如果你在家务里设计一个回调的时候是这么设计的,使用的时候是这么使用的, 到了杠里就可以改成这么写了。另外,大多数情况下,匿名函数还能再简化一点,写成两个表达式的形式 啊。快九分钟了,终于讲到 lamda 了。如果 lamda 是函数的最后一个参数,你可以把 lamda 写在括号的外面。而如果 lamda 是函数唯一的参数,你还可以直接把括号去了。另外,如果这个 lamda 是单参数的,他的这个参数也可以省略到不写。 哎,不错,单参数的时候只要不用这个参数,就可以直接不写了。其实就算用也可以不写,因为看了 莱姆岛,对于省略的唯一参数有默认的名字, it 有点爽哈。不过我们先停下想一想这个莱姆岛这也不写那也不写的, 他不迷茫吗?他是怎么知道自己的参数类型和返回之类型的?我调用的函数在声明的地方有明确的参数信息吧,这里面把这个参数的参数类型和返回之类型写的清清楚楚吧。所以 lem 的才不用写的。 所以当你要把一个匿名函数复职给变量,而不是作为函数参数传递的时候,如果也简写成莱姆德的形式,就不能省略掉莱姆德的参数类型了。 为什么?因为他无法从上下文中推断出这个参数的类型啊。如果你出于场景的需求或者个人偏好,就是想在这里省掉参数类型,那你需要给左边的变量知名类型。 另外, lamda 的返回值不是用 return 来返回,而是直接取最后一行代码的纸。这个一定注意, lamda 的返回值别写 return。 如果你写了,他会把这个作为一套外层的函数的返回词来直接结束外层函数。 如果你只是想返回莱姆的,这么写就出错了。另外,因为莱姆的是个代码块,他总能根据最后一行代码来推断出返回之类型,所以他的返回职类型确实可以不写。实际上看到的莱姆的也是写不了返回之类型的,语法上就不支持。现在我再听一下,我们想一想匿名函数和莱姆的 他们到底是什么?我们先看匿名函数,他可以作为参数传递,也可以复制给变量,对吧?但是刚才我们也说过了,函数之不能作为参数传递,也不能复制给变量的,是吧?那为什么匿名函数就这么特殊呢?因为看了等匿名函数,他不是函数, 他是个对象。匿名函数虽然名字里有函数两个字,包括英文的原名也是 nanamass 方式,但他其实不是函数,而是一个对象,一个函数类型的。对 他和双冒号加函数名是一个东西,和函数不是,所以你才可以直接把他作为函数的参数来传递以及复制给电量。同理, lamda 其实也是一个函数类型的对象而已,你能怎么使用双冒号加函数名,就能怎么使用匿名函数,以及怎么使用 lamda。 这就是卡伦的匿名函数以及蓝贝贝达士的本质,他们都是函数类型的。对 calendar lamda 和 javabada lamda 是不一样的, javebada lamda 只是一种便捷写法,本质上并没有功能上的突破。而卡伦的 lamda 是实实在在的对象。在,你知道吧,在卡伦里,函数并不能传递,传递的是对 和匿名函数。荷兰的表达是,其实都是对象这些本质之后,你以后去写卡朗的高级函数,会非常轻松,非常舒畅。卡朗官方文档里面对于双冒号加上韩束名的写法叫做 function reference 函数引用故意引导大家认为这个引用是指向原函数的,这是为了简化事情的逻辑,让大家更好上手考了。但这种逻辑是有毒的,一旦你信了他,你对于匿名函数和莱姆达就怎么也搞不清楚了。对于高冷的莱姆达,有很多从加法过来的人表示好用好用,但 不会写,你都不会写,那你是怎么会用的呢?加法从八开始引入了对 land 的支持,对于单抽奖方法的借口,简称 sam 借口、 single abstract method 借口。对于这一类借口,加法八允许你用 land 表达是来创建匿名类对象,但他本质上还是在创建一个匿名类对象,只是种简化写法而已。 所以加把吧的 m 的只靠代码的自动补全就基本能写了。而卡里的 m 的跟加把吧本质上就是不同的,因为卡里的 m 的是实实在在的函数类型的对象,功能更强,写法更多更灵活。所以很多人从加把过来就有点搞 我不明白了。另外呢,看了是不支持用单的表达式来简写匿名类对象的,因为我们有函数类型的参数嘛,所以这种单函数接口的写法从根本上 就没必要了,那你还支持他干嘛?不过当和加瓦交互的时候,康冷是支持这种用法的,当你的函数参数是加瓦的单抽降方法的接口的时候,你依然可以使用莱姆的来写参数,但这其实也不是甘冷增加了功能。而 而对于来自 java 的单抽象方法的接口,高冷会为他们额外创建一个把参数替换为函数类型的调接方法,让你可以间接的创建 java 的匿名类对象。这就是为什么 你会发现,当你在 colony 调用 musiciaba 这个类的 set on click listener 的时候,可以传 limit 来给他创建昂克 listen 对象。但 你照着同样的写法写一个卡朗的接口,你却不能传连的。因为卡愣希望我们直接使用函数类型的参数, 而不是用接口这种折中方案。好,这就是卡愣的高阶函数。匿名函数和 lem 的表达是简单总结一下,在杠里有一类 java 中不存在的类型叫做函数类型,这一类类型的对象在可以当函数来使用的同时,还能作为函数的参数,函数的返回值以及复制给别。 创建一个函数类型的对象有三种方式,双方号加函数、名匿名函数以及莱姆的。一定要记住,双梦号加函数,名匿名函数以及莱姆的本质上都是函数类型的对象。在杠里,匿名函数不是函数,莱姆的,也不是什么 所谓玄学的,他只是个代码块,没法归类,看到 lm 到可以归类他属于函数类型的对象。当然了,这里面的各种细节还有很多,这个你可以自己学去,我就不管你了。下期内容是看到了扩展属性和扩展函数,关注我不错过我的任何新内容,大家拜拜。