Kotlin之let,apply,with,run函数区别(转)
转自:https://blog.csdn.net/guijiaoba/article/details/54615036
Kotlin之let,apply,with,run函数区别
重新整理
重新整理了各种函数的区别,请移步到这里。
以下作废
很长一段时间内都一直使用Kotlin这门语言,也只是纯粹使用简单语法,最近有时候写的代码,编辑器自动提示使用let等函数,然后就专门花点时间研究了下。
let
首先let()的定义是这样的,默认当前这个对象作为闭包的it参数,返回值是函数里面最后一行,或者指定return
fun <T, R> T.let(f: (T) -> R): R = f(this)
- 1
简单示例:
fun testLet(): Int {
// fun <T, R> T.let(f: (T) -> R): R { f(this)}
"testLet".let {
println(it)
println(it)
println(it)
return 1
}
}
//运行结果
//testLet
//testLet
//testLet
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
可以看看最后生成的class文件,代码已经经过格式化了,编译器只是在我们原先的变量后面添加了let里面的内容。
public static final int testLet() {
String str1 = "testLet";
String it = (String)str1;
int $i$a$1$let;
System.out.println(it);
System.out.println(it);
System.out.println(it);
return 1;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
来个复杂一定的例子
fun testLet(): Int {
// fun <T, R> T.let(f: (T) -> R): R { f(this)}
"testLet".let {
if (Random().nextBoolean()) {
println(it)
return 1
} else {
println(it)
return 2
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
编译过后的class文件
public static final int testLet() {
String str1 = "testLet";
String it = (String)str1;
int $i$a$1$let;
if (new Random().nextBoolean())
{
System.out.println(it);
return 1;
}
System.out.println(it);
return 2;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
apply
apply函数是这样的,调用某对象的apply函数,在函数范围内,可以任意调用该对象的任意方法,并返回该对象
fun <T> T.apply(f: T.() -> Unit): T { f(); return this }
- 1
代码示例
fun testApply() {
// fun <T> T.apply(f: T.() -> Unit): T { f(); return this }
ArrayList<String>().apply {
add("testApply")
add("testApply")
add("testApply")
println("this = " + this)
}.let { println(it) }
}
// 运行结果
// this = [testApply, testApply, testApply]
// [testApply, testApply, testApply]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
编译过后的class文件
public static final void testApply()
{
ArrayList localArrayList1 = new ArrayList();
ArrayList localArrayList2 = (ArrayList)localArrayList1;
int $i$a$1$apply;
ArrayList $receiver;
$receiver.add("testApply");
$receiver.add("testApply");
$receiver.add("testApply");
String str = "this = " + $receiver;
System.out.println(str);
localArrayList1 = localArrayList1;
ArrayList it = (ArrayList)localArrayList1;
int $i$a$2$let;
System.out.println(it);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
with
with函数是一个单独的函数,并不是Kotlin中的extension,所以调用方式有点不一样,返回是最后一行,然后可以直接调用对象的方法,感觉像是let和apply的结合。
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
- 1
代码示例:
fun testWith() {
// fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
with(ArrayList<String>()) {
add("testWith")
add("testWith")
add("testWith")
println("this = " + this)
}.let { println(it) }
}
// 运行结果
// this = [testWith, testWith, testWith]
// kotlin.Unit
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
class文件
public static final void testWith()
{
Object localObject = new ArrayList();
ArrayList localArrayList1 = (ArrayList)localObject;
int $i$a$1$with;
ArrayList $receiver;
$receiver.add("testWith");
$receiver.add("testWith");
$receiver.add("testWith");
String str = "this = " + $receiver;
System.out.println(str);
localObject = Unit.INSTANCE;
Unit it = (Unit)localObject;
int $i$a$2$let;
System.out.println(it);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
run
run函数和apply函数很像,只不过run函数是使用最后一行的返回,apply返回当前自己的对象。
fun <T, R> T.run(f: T.() -> R): R = f()
- 1
代码示例
fun testRun() {
// fun <T, R> T.run(f: T.() -> R): R = f()
"testRun".run {
println("this = " + this)
}.let { println(it) }
}
// 运行结果
// this = testRun
// kotlin.Unit
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
class文件
public static final void testRun()
{
Object localObject = "testRun";
String str1 = (String)localObject;
int $i$a$1$run;
String $receiver;
String str2 = "this = " + $receiver;
System.out.println(str2);
localObject = Unit.INSTANCE;
Unit it = (Unit)localObject;
int $i$a$2$let;
System.out.println(it);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
总结
怎么样,是不是看晕了,没关系,我们来总结下。
| 函数名 | 定义 | 参数 | 返回值 | extension | 其他 |
|---|---|---|---|---|---|
| let | fun T.let(f: (T) -> R): R = f(this) | it | 闭包返回 | 是 | |
| apply | fun T.apply(f: T.() -> Unit): T { f(); return this } | 无,可以使用this | this | 是 | |
| with | fun with(receiver: T, f: T.() -> R): R = receiver.f() | 无,可以使用this | 闭包返回 | 否 | 调用方式与其他不同 |
| run | fun T.run(f: T.() -> R): R = f() | 无,可以使用this | 闭包返回 | 是 |
Kotlin之let,apply,with,run函数区别(转)的更多相关文章
- [Java] Thread的start()和run()函数区别
1.start()方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码: 通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状 ...
- Kotlin 之 let、with、run、apply、also 函数的使用
一.内联拓展函数 let let 扩展函数的实际上是一个作用域函数,当你需要去定义一个变量在一个特定的作用域范围内,let函数的是一个不错的选择:let函数另一个作用就是可以避免写一些判断null的操 ...
- 瞬间记住Javascript中apply与call的区别
关于Javascript函数的apply与call方法的用法,网上的文章很多,我就不多话了.apply和call的作用很相似,但使用方式有区别 apply与call的第一个参数都是一个对象,这个对象就 ...
- 改变this指针的apply,call,bind的区别
apply.call 在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向. Jav ...
- apply()和call()的区别
这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值. apply()接收两个参数:一个参数是在其中运行的作用域,另一个是参数数组(可以是Array实例,也可以是arg ...
- 【JavaScript】apply和call的区别在哪?
我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这里我做如下笔记,希望和大家 ...
- android SharedPreferences apply和commit的区别
1.apply没有返回值而commit返回boolean表明修改是否提交成功2.apply是将修改数据原子提交到内存, 而后异步真正提交到硬件磁盘, 而commit是同步的提交到硬件磁盘3.apply ...
- JavaScript之apply()和call()的区别
我 在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示 例,总算是看的有点眉目了,在这里我做如下笔记,希望和 ...
- JS 中的this指向问题和call、apply、bind的区别
this的指向问题 一般情况下this对象指向调用函数的对象,全局环境中执行函数this对象指向window. function a(){ console.log(this); //输出函数a中的th ...
随机推荐
- procixx和最近调试的坑
流程: 1.procixx/vivado 配置soc硬件信息,导出FSBL.out: 2.配置uboot dts,生成u-boot (需要打开的硬件 配置为status = "okay&qu ...
- QT的总结文章(转)
★了解Qt和C++的关系 ★掌握Qt的信号/槽机制的原理和使用方法 ★了解Qt的元对象系统 ★掌握Qt的架构 ★理解Qt的事件模型,掌握其使用的时机 信号与槽.元对象系统.事件模型是Qt机制的 ...
- Java实现线程的两种方式?Thread类实现了Runnable接口吗?
Thread类实现了Runnable接口吗? 我们看看源码中对与Thread类的部分声明 public class Thread implements Runnable { /* Make sure ...
- hive中为分区表增加字段需要注意默认不会修改已有分区的字段,导致查询时新增字段为null
若向hive表添加字段,通常会使用下面这种语句 alter table default.testparquet add columns(c8 string); 但是对于分区表来说, 1. 若新建的分区 ...
- spring boot 热部署devtools实现(成功,主要是添加依赖后配置setting)
1.devtools spring为开发者提供了一个名为spring-boot-devtools的模块来使Spring Boot应用支持热部署,提高开发者的开发效率,无需手动重启Spring Boot ...
- 配置 Ceph 内外网分离
https://www.jianshu.com/p/42ab1f6dc6de 1. 为什么要做内外网分离 先明确一下这么做的必要性.Ceph 的客户端,如 RADOSGW,RBD 等,会直接和 O ...
- mybatis如何通过接口查找对应的mapper.xml及方法执行详解
转:http://www.jb51.net/article/116402.htm 本文主要介绍的是关于mybatis通过接口查找对应mapper.xml及方法执行的相关内容,下面话不多说,来看看详细的 ...
- vux使用方法
# 使用vux及vuex-i18n需要做的工作 ### 1.首先需要安装vux ### 2.需要安装vux-loader ### 3.需要安装vuex ### 4.需要安装vuex-i18n ### ...
- git开发实战:认识git
git简介: git是分布式版本控制系统,相比较svn相比,git会在本地保存完整的提交记录,即使远程服务器宕机数据消失,可以将本地分支提交到远程服务器,本地分支会保存完整的记录.只要文件提交到git ...
- 我的WordPress站点
读取VDI文件 SSL和TLS Windows下使用vim的最佳方案:Sublime gdb用法 VMware的Guest与Host进行通信的三种方式 加密与解密 漫谈保护模式 processing学 ...