当前位置: 首页 > wzjs >正文

施甸网站建设利搜网站排名软件

施甸网站建设,利搜网站排名软件,绵阳网站建设软件有哪些,做模板网站简单吗Kotlin扩展函数 Kotlin 的扩展函数是 Kotlin 中非常强大且实用的功能。它允许你为现有的类添加新的方法,而不需要修改其源代码。这意味着你可以在已有的类上“扩展”新的功能,使用起来就像是原本就存在这些方法一样。 扩展函数的基本语法 fun 类名.方…

Kotlin扩展函数

Kotlin 的扩展函数是 Kotlin 中非常强大且实用的功能。它允许你为现有的类添加新的方法,而不需要修改其源代码。这意味着你可以在已有的类上“扩展”新的功能,使用起来就像是原本就存在这些方法一样。

扩展函数的基本语法

fun 类名.方法名(参数列表): 返回类型 {// 函数体
}

我们去看看Kotlin官方为我们实现的扩展函数例子,就拿官方对Float的扩展方法pow()举例,Float类本身并没有实现乘方功能的方法,在没有这个方法之前,我们只能使用Math类的静态方法进行乘方运算:

Math.pow(2.0, 2.0

当我们在Kotlin中这样写,编译器会提示我们:
在这里插入图片描述
这里告诉我们我们可以用Kotlin的函数如下:

2.0.pow(2.0)//pow函数的实现
public actual inline fun Double.pow(x: Double): Double = nativeMath.pow(this, x)

我们看到这个pow函数是Kotlin对Double类的扩展。我们也可以自己多现有的类进行扩展,例如我们需要打印字符串的最后一个字符,我们可以对String类进行扩展:

fun String.printLastChar() {println(this[length - 1])
}fun main() {//对扩展函数的调用"Hello".printLastChar()//取函数的引用使用invoke进行调用String::printLastChar.invoke("Hello")//直接调用函数引用(String::printLastChar)("Hello")
}

扩展函数的作用域

扩展函数可以定义在Kotlin文件中,是其不属于任何一个类,其他地方都可以使用,类似于上面的String.printLastChar()方法;另外一种是可以声明在类中:

class ExtensionsSample{fun normalFun(){"Java".printLastChar()"Kotlin".printFirstChar()}private fun String.printFirstChar() {println(this[0])}
}

如果扩展函数定义在某个类中,而定义在类中,printFirstChar()方法即是ExtensionsSample类的成员函数,同时又是String类的扩展函数,String类是这个扩展函数的Receiver,定义在类中的扩展函数的作用范围是类及其内部类。在kotlin中也无法通过对象调用定义在其内部的扩展方法,即是限定符是默认的public

扩展函数的原理

我们对扩展函数所在的文件进行反编译,看其生成的字节码文件反编译的结果如下:

public final void printFirstChar(@NotNull String $this$printFirstChar) {Intrinsics.checkNotNullParameter($this$printFirstChar, "$this$printFirstChar");char var2 = $this$printFirstChar.charAt(0);System.out.println(var2);
}

扩展函数并不是修改原有类的实际代码,它是在编译时通过生成额外的代码来实现的。虽然你能通过扩展函数像访问原有方法一样调用新方法,但它们实际上并没有改变原有类的行为。扩展函数只是通过静态解析(编译时确定类型)来实现的。

因此,扩展函数无法真正覆盖或修改类中的已有方法,也不能访问类的私有成员。

Kotlin扩展属性

Kotlin 还支持扩展属性,它可以为类添加属性,但只能是可读属性(即没有 setter 方法),因为扩展属性不能存储实际的数据。

val 类名.属性名: 类型get() = // 计算属性的值
val String.lastChar: Charget() = this[this.length - 1]fun main() {println("HelloWorld".lastChar)
}

在某些情况下,我们不需要扩展方法,只需要扩展属性即可。

inline

Kotlin官方文档在介绍inline关键字中写道使用不当是会有一定的性能问题的,官方的原话是这样介绍:
Using higher-order functions imposes certain runtime penalties: each function is an object, and it captures a closure. A closure is a scope of variables that can be accessed in the body of the function. Memory allocations (both for function objects and classes) and virtual calls introduce runtime overhead.
使用高阶函数会带来一些运行时的效率损失:每一个函数都是一个对象,并且会捕获一个闭包。 闭包那些在函数体内会访问到的变量的作用域。 内存分配(对于函数对象和类)和虚拟调用会引入运行时间开销。但是在许多情况下通过内联化 lambda 表达式可以消除这类的开销。

  • 使用 inline 修饰的函数,会在调用点处将函数的代码“展开”(也叫内联),而不是生成一个实际的函数调用。这意味着函数体的代码会直接插入到调用它的地方,这避免了函数调用所带来的栈帧创建和返回的性能开销。
  • 高阶函数指的是接受另一个函数作为参数的函数。在没有 inline 时,传入的函数会在堆栈上创建一个对象,并通过引用进行调用,这会导致额外的内存分配和垃圾回收。使用 inline 后,传入的函数会直接嵌入到调用点,避免了创建和传递函数对象的开销。
  • 由于内联函数的代码直接插入到调用的地方,Kotlin 会避免为这些高阶函数(例如 lambda 表达式)分配对象,从而减少了内存的消耗。

如果一个高阶函数在循环中被调用,或者在Android中的onDraw方法中调用,高阶函数在执行的过程中就会创建临时对象,短时间创建大量对象,并且这些对象的生命周期都很短,就会造成内存抖动

fun main() {highOrder(5) {println(it)it}
}fun highOrder(number: Int, callBack: (Int) -> Int) {callBack(number + 1)
}

我们对上面的文件进行反编译可以发现确实是在执行的时候是通过Function1
这个类来实现我们的高阶函数传入的函数

public static final void main() {highOrder(5, (Function1)null.INSTANCE);
}// $FF: synthetic method
public static void main(String[] var0) {main();
}public static final void highOrder(int number, @NotNull Function1 callBack) {Intrinsics.checkNotNullParameter(callBack, "callBack");callBack.invoke(number + 1);
}

而我们给高阶函数添加highOrder前面添加关键字inline之后,让他变成内联函数在经过反编译可以看到:

public static final void main() {int number$iv = 5;int $i$f$highOrder = false;int it = number$iv + 1;int var3 = false;System.out.println(it);
}

而这里就是直接把我们传入的lambda表达式具体的执行逻辑直接放到了这里,由此可见inline关键字的主要作用就是减少调用栈的深度,并能够优化高阶函数在执行时的性能问题。

noinline

如果不希望内联所有传给内联函数的 lambda 表达式参数都内联,那么可以用 noinline 修饰符标记不希望内联的函数参数:

inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) { …… }

假设有一种场景,你的高阶函数传入了两个函数参数,你希望其中的一个函数参数以函数引用的方式作为返回值,就可以使用到noinline关键字:

inline fun foo(callBack: (Int) -> Int, noinline result: () -> Unit): () -> Unit {callBack(2)return result
}

noinline的作用就是局部的、有指向性的关闭Kotlin的内联优化。

crossinline

我们先来看一段代码:

fun main() {println("This is before of heightFunc")heightFunc {return@heightFunc}println("This is after of heightFunc")
}fun heightFunc(call: () -> Unit) {call()println("This is inner of heightFunc")
}

这样写所有的打印的地方都会执行,而使用inline关键字标记heightFunc函数之后,并且去掉return的标签,那么结果就发生了改变

fun main() {println("This is before of heightFunc")heightFunc {return}println("This is after of heightFunc")
}fun heightFunc(call: () -> Unit) {call()println("This is inner of heightFunc")
}

最终的执行结果为只打印了This is before of heightFunc,我们通过内联函数的优化可以想到其中的原因。
当我们需要在内联函数中间接的调用传入的lambda表达式时,编译器会给我们如下提示:
在这里插入图片描述
而我们在外面调用内联函数,在lambda表达式中使用return的时候,是不被允许的,要使用必须加标签显示的指定退出那个函数
在这里插入图片描述
所以crossinline的作用就是如果你希望禁止 lambda 中的 return 语句影响外部函数的执行,可以使用 crossinline。这块lambda中的return和内联函数结合起来使用具体得多写,编译器会给出提示。

http://www.dtcms.com/wzjs/395827.html

相关文章:

  • 怎么做学校网站百度app下载最新版本
  • 辽宁做网站哪家好广告投放方案
  • 中山 环保 骏域网站建设专家今日头条官方正版
  • 泉州做网站公司创意设计
  • 做网站公众号多少钱长尾词挖掘
  • 宝安网站设计制作郭生b如何优化网站
  • 做网站最省钱百度seo推广计划类型包括
  • 电子商务网站建设与管理学习心得百度账号查询
  • 重庆最有效的网站推广湖北seo网站推广
  • 百度推广销售话术厦门seo培训
  • 免费软件聊天免费找女朋友泰安网站优化公司
  • 医疗网站seo怎么做职业技能培训平台
  • html5学习网站seo哪里有培训
  • 只买域名怎么做网站ip域名解析查询
  • 怎样做淘客网站怎么推广自己的微信号
  • 建设行业信息和技术应用服务网站户外广告
  • 公司做二手网站的用意官网百度
  • 怎么做自己的网址深圳网站优化软件
  • 如何弄微信小程序西安官网seo公司
  • 做电影网站需要多大空间优质外链平台
  • 免费电商网站建设做品牌推广应该怎么做
  • 我厂有大量手工活外发加工seo线下培训班
  • 在eclipse中做网站开发新开传奇网站发布站
  • 怎样找素材做网站seo对网络推广的作用是什么?
  • 广东网站设计公司价格腾讯新闻最新消息
  • 佛山网站建设公司电话百度竞价排名规则
  • wordpress爆破软件seo分析是什么意思
  • 站长工具国产2023网络营销心得体会800字
  • 自己的网站怎么做实时监控百度搜索什么关键词能搜到网站
  • 免费发布信息网站大全下载安装店面怎么做位置定位