Kotlin内置函数之also

Kotlin 的 ‌**also‌ 函数是一个‌ 作用域函数‌,主要用于在链式调用中执行‌ 副作用操作**‌(如日志记录、数据校验等),同时保留原对象并返回它。与 apply 类似,但它通过 it 引用对象,而非隐式 this。以下是其核心特性和典型用法:


基本特性

  1. 函数签名‌:

    kotlin 复制代码
    public inline fun <T> T.also(block: (T) -> Unit): T
    • T 的扩展函数,接收一个以 T 为参数的 lambda((T) -> Unit)。
    • 返回原对象本身 ‌(即 this),允许链式调用。
  2. 核心用途‌:

    • 在对象操作流程中插入‌副作用代码‌(如日志、校验)。
    • 链式调用中保留原对象,同时执行额外操作。

使用示例

示例 1:记录对象状态

scss 复制代码
val list = listOf(1, 2, 3)
    .also { println("初始列表: $it") } // 打印日志,返回原列表
    .map { it * 2 }
    .also { println("处理后列表: $it") }

示例 2:数据校验

kotlin 复制代码
fun createUser(name: String, age: Int) = User(name, age)
    .also { 
        require(it.age >= 0) { "年龄不能为负数" } // 校验年龄
    }

示例 3:链式调用中修改对象

scss 复制代码
val file = File("data.txt")
    .also { it.createNewFile() } // 创建文件,返回 File 对象
    .also { it.setWritable(true) }

apply 的区别

函数 参数形式 对象引用 典型场景
‌**also**‌ (T) -> Unit it 副作用操作(如日志、校验)
‌**apply**‌ T.() -> Unit this 对象属性初始化配置
  • ‌**also‌ 更强调‌ 显式引用对象**‌(通过 it),适合需要操作对象但无需直接访问其属性的场景。
  • ‌**apply‌ 更适用于‌ 隐式配置对象属性**‌(直接通过 this 访问)。

关键细节

  1. 显式对象引用 ‌:在 also 的 lambda 中,通过 it 操作对象(可自定义参数名):

    scss 复制代码
    user.also { u ->
        println(u.name) // 重命名为 u,避免嵌套作用域中的 it 歧义
    }
  2. 空安全操作 ‌:结合 ?. 安全调用,避免空指针:

    kotlin 复制代码
    val nameLength = user?.name
        ?.also { println("非空名称: $it") } // 仅在 name 非空时执行
        ?.length
  3. 与构造函数配合‌:

    ini 复制代码
    val person = Person("Alice").also {
        it.age = 30 // 补充初始化构造函数未涵盖的属性
    }

适用场景

  1. 调试日志‌:

    scss 复制代码
    dataProcessor.process(data)
        .also { log("处理结果: $it") }
        .upload()
  2. 链式调用中插入操作‌:

    scss 复制代码
    val result = listOf(1, 2, 3)
        .filter { it > 1 }
        .also { println("过滤后集合: $it") } // 中间步骤日志
        .sum()
  3. 对象深拷贝或备份‌:

    scss 复制代码
    val original = mutableListOf(1, 2, 3)
    val copy = original.toList().also { 
        original.clear() // 不影响 copy
    }
  4. 资源释放前操作‌:

    scss 复制代码
    connection.open()
        .also { it.setTimeout(5000) }
        .use { /* 自动关闭连接 */ }

注意事项

  1. 避免滥用 ‌:若仅需配置对象属性,优先用 apply(代码更简洁)。
  2. 副作用管理 ‌:确保 also 中的操作不会破坏对象状态或逻辑。
  3. 性能优化‌:作为内联函数,无额外运行时开销。

总结

  • 使用 also 的场景:

    • 需在链式调用中‌插入日志、校验等副作用代码‌。
    • 需显式引用对象(it)执行操作,同时保留原对象。
  • apply 的对比:

    • also:显式操作对象,强调副作用。
    • apply:隐式配置对象属性,强调初始化。
相关推荐
快点好好学习吧27 分钟前
phpize 依赖 php-config 获取 PHP 信息的庖丁解牛
android·开发语言·php
是誰萆微了承諾28 分钟前
php 对接deepseek
android·开发语言·php
Dxy12393102161 小时前
MySQL如何加唯一索引
android·数据库·mysql
冠希陈、3 小时前
PHP 判断是否是移动端,更新鸿蒙系统
android·开发语言·php
晚霞的不甘6 小时前
Flutter for OpenHarmony从零到一:构建《冰火人》双人合作闯关游戏
android·flutter·游戏·前端框架·全文检索·交互
2601_949833396 小时前
flutter_for_openharmony口腔护理app实战+饮食记录实现
android·javascript·flutter
独自破碎E6 小时前
【滑动窗口+字符计数数组】LCR_014_字符串的排列
android·java·开发语言
stevenzqzq6 小时前
compose 中 align和Arrangement的区别
android·compose
VincentWei956 小时前
Compose:MutableState 和 mutableStateOf
android
jian110586 小时前
Android studio配置flutter,mac Android studio 发现苹果手机设备
android·flutter·android studio