Kotlin专题「二十三」:引用详解 :: (类引用、属性引用、函数引用、绑定引用)

本文介绍Kotlin中的引用,包括成员引用、类引用和绑定引用。成员引用可将函数转换成值,有函数引用、属性引用等多种形式;类引用可获得Kotlin类的运行时引用;绑定引用能捕捉特定实例对象上的方法引用。使用反射需添加JVM依赖。

前言:没有谁的幸运,凭空而来,只有当你足够努力,你才会足够幸运。这世界不会辜负每一份努力和坚持,时光不会怠慢执着而勇敢的每一个人!

一、概述

  反射是一组语言和库特性,允许程序在运行时访问程序结构的一类特性。程序结构包括类、接口、函数、属性等语法特性。Kotlin 使函数和属性成为该语言的一级公民,而内省它们(即在运行时学习属性或函数的名称或类型)与简单地使用函数或响应式风格紧密相连。

最基本的反射特性是获得对 Kotlin 运行时的引用。除了访问程序结构之外,对函数、属性和构造函数的引用还可以作为函数类型的实例调用。今天来给大家介绍 Kotlin 中的引用,双冒号 :: 表示引用,有属性引用、函数引用、类引用、构造函数引用、扩展函数引用、绑定引用等等。

1.1 添加 JVM 依赖

在 JVM 平台上,使用反射特性所需要的运行组件在 Kotlin 编译器发行版中作为单独的工作 Kotlin -reflect.jar 分发。这样做是为了减少不使用反射特性的应用程序所需要的运行时库大小。也就是说你要添加这个 jar 包才可以使用反射特性。

  • 1、在 Gradle 中添加:
dependencies {
   
   
  implementation("org.jetbrains.kotlin:kotlin-reflect:1.4.21")
}
  • 2、或者添加 Maven 仓库:
<dependencies>
    <dependency>
        <groupId>org.jetbrains.kotlin</groupId>
        <artifactId>kotlin-reflect</artifactId>
    </dependency>
</dependencies>

另外,如果你不使用 Gradle 或 Maven,请确保在项目的类路径中有 kotlin-reflect.jar 包。在其他支持的请况下(IntelliJ IDEA项目,使用命令行编译器或Ant),它是默认添加的。在命令行编译器和 Ant 中,可以使用 -no-reflect 编译器选项从类路径种排除 kotlin-reflect.jar

二、 成员引用

2.1 为什么使用引用?

Lambda 表达式可以直接把一个代码块作为一个参数传递给函数,但是如果要当做参数传递的代码已经被定义成了函数,此时还需要重复写一个代码块传递过去吗?肯定不是,Kotlin拒绝重复啰嗦的代码,这时候就需要 把函数转换成一个值,这种方式称为 成员引用

    val persons = arrayListOf(Person("Java", 20), Person("Android", 5))
    println(persons.maxBy({
   
    p: Person -> p.age }))

{ p: Person -> p.age } 表达式可以用成员引用的方式 Person::age 替换。成员引用和调用函数的 lambda 具有一样的类型,所以可以相互转换。如下:

    //println(persons.maxBy({ p: Person -> p.age }))
    println(persons.maxBy(Person::age))//成员的引用类型和maxBy()传入Lambda表达式的一致

2.2 成员引用的基本语法

上面这种用法称为成员引用,它提供简明语法,来创建一个单个方法或者单个属性的函数值,使用 :: 运算符来转换。成员引用由类名,双冒号,成员三个元素组成。成员是函数名表示引用函数,成员是属性表示引用属性。
在这里插入图片描述

所有可调用引用的通用超类型是 KCallable<out R> ,其中 R 是返回值类型,可能是属性的属性类型,也可能是构造函数的构造类型。

2.3 函数引用

成员是函数名表示函数引用。这种情况省略了类名称,直接以 :: 开头。当我们这样声明一个命名函数时:

	fun isOld(x: Int) = x > 18

可以将其作为函数类型值使用,将它传递给另一个函数,我们可以使用函数引用:

	val numbers = arrayListOf(10, 20, 30)
	println(numbers.filter(::isOld))//打印:[20, 30]

函数引用 ::isOld 被当做实参传递给 filter() 函数,它会调用相应的函数。这里 ::isOld 是一个函数类型 (Int) -> Boolean 的值。

函数引用属于 KFunction<out R> 子类型之一,这取决于函数计数,例如:KFunction3<T1, T2, T3, R>

下面列出几种函数引用使用的场景:

(1)重载函数引用

函数引用可以与重载函数一起使用,当参数类型从上下文中推断出来时。例如:

    fun isOld(x: Int) = x > 18
	//函数重载
    fun isOld(str: String) = str == "Java" || str == "Android" || str == "Kotlin"

	val numbers = arrayListOf(10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值