Kotlin - 引用操作符 ::

一、概念

将类、函数、属性、构造函数等程序元素转化为可传递的引用对象,就像给这些元素贴上标签,方便在代码中灵活调用。

1.1 使用场景

不能引用局部函数、匿名函数和 Lambda 表达式 ,这些都属于不可引用的实体,如果强行引用,编译时会报错。

|--------|------------------------------------------------------------------|
| 类引用 | 很多时候需要传入 Java 的 Class 对象,通过【类名::class.java】来转换。 |
| 函数引用 | 将函数作为参数传递或赋值给变量,实现函数式编程的高阶特性。极大地增强了代码的灵活性与可扩展性,方便进行函数组合、策略模式等设计。 |
| 属性引用 | 获取属性的 getter 或 setter,实现对属性的间接访问与操作。这在数据绑定、属性监听等场景中十分实用。 |
| 构造函数引用 | 创建对象的工厂函数,便于根据不同需求动态创建对象。在对象池管理、依赖注入等场景中发挥重要作用。 |

1.2 KClass

通过【类名::class】获取 Kotlin 特有的类描述对象,它提供了更丰富的元信息,如simpleName(类名)、qualifiedName(完整类名)、isData(是否为数据类)等,这些额外信息使得在 Kotlin 中进行反射操作和类型处理更加便捷和强大,充分体现了 Kotlin 在语言设计上对开发者的友好和对现代编程需求的支持。

二、使用

2.1 类引用(类名::class.java)

Kotlin 复制代码
retrofit.create(ApiService::class.java)

2.2 函数引用

2.2.1 静态引用(类名::函数名)

静态引用在调用时,需要传入一个接收者对象。

Kotlin 复制代码
class Calculator {
    fun add(a: Int, b: Int): Int = a + b
}
val unboundAdd: Calculator.(Int, Int) -> Int = Calculator::add
val calculator = Calculator()
val result = unboundAdd(calculator, 2, 3)
println(result)  // 输出5

2.2.2 绑定引用(实例名::函数名)

绑定引用已经关联到了特定的实例,在调用时不需要再重复传递接收者对象。

Kotlin 复制代码
class Calculator {
    fun add(a: Int, b: Int): Int = a + b
}
val calculator = Calculator()
val boundAdd: (Int, Int) -> Int = calculator::add
val result = boundAdd(2, 3)
println(result)  // 输出5

2.2.3 顶层函数绑定引用(::函数)

Kotlin 复制代码
fun isEven(number: Int): Boolean = number % 2 == 0
val numbers = listOf(1, 2, 3, 4, 5, 6)
val evens = numbers.filter(::isEven)
println(evens)  // 输出[2, 4, 6]

2.3 属性引用(类名::属性名)

Kotlin 复制代码
class Person(
    val name: String,
    var age: Int
)

val nameGetter: (Person) -> String = Person::name
val person = Person("Alice", 30)
println(nameGetter(person))  // 输出Alice

val ageSetter: (Person, Int) -> Unit = Person::age
ageSetter(person, 31)
println(person.age)  // 输出31

2.4 构造函数引用(::类名)

java 复制代码
class User(val name: String)

val userFactory: (String) -> User = ::User
val newUser = userFactory("Bob")
println(newUser.name)  // 输出Bob

三、优化调用场景

3.1 简化 Lambda 表达式,提升可读性

函数引用是对已存在的具名函数的引用,不会像 Lambda 每次使用时都创建匿名内部类对象,从而减少了对象创建的开销。

Kotlin 复制代码
val strings = listOf("apple", "banana", "cherry")
//一般使用
val lengths = strings.map { it.length }
//优化后使用
val lengths = strings.map(String::length)

3.2 反射

Kotlin 复制代码
class Animal {
    fun makeSound() { println("Some sound") }
}
Kotlin 复制代码
fun main() {
    val className = "Animal"
    val kClass = Class.forName(className).kotlin
    val instance = kClass.constructors.first().call()
    val method = kClass.memberFunctions.find { it.name == "makeSound" }
    method?.call(instance)
}
相关推荐
千里马学框架2 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台2 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone2 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
ai2work3 天前
ch23 综合复刻:从零做一个最小可用版本(capstone)
kotlin
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
ai2work3 天前
ch21 签名、校验与发版
kotlin
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui