20260320-前五章的一些个人补充知识

20260320-前五章的一些个人补充知识 之后会在这里随时补充一些知识点一、二、三、四、类与面向对象编程4.1、android的内部类和kotlin的是不一样的定义在java中public class OuterClass { // 1. 静态内部类嵌套内部类- 不持有外部类引用 static class StaticInnerClass { } // 2. 非静态内部类普通内部类- 持有外部类引用 class NonStaticInnerClass { } // 3. 匿名内部类 - 持有外部类引用 Runnable runnable new Runnable() { Override public void run() { } }; }静态内部类不持有外部类引用非静态内部类持有外部类引用匿名内部类持有外部类引用原理当编译器编译非静态内部类时会自动添加一个指向外部类的引用字段。public class OuterClass { private int outerField 10; class InnerClass { public void accessOuter() { System.out.println(outerField); } } } 编译后的字节码简化 // OuterClass$InnerClass.class class OuterClass$InnerClass { // 编译器自动添加的外部类引用字段 final synthetic OuterClass this$0; // 构造函数接收外部类引用 OuterClass$InnerClass(OuterClass outer) { this$0 outer; } public void accessOuter() { // 通过this$0访问外部类成员 System.out.println(this$0.outerField); } }自动添加字段编译器为每个非静态内部类添加一个this$0字段synthetic修饰符表示这是编译器生成的构造函数修改构造函数自动接收外部类引用并保存访问外部成员所有对外部类成员的访问都通过this$0进行synthetic 关键字标记编译器自动生成的代码在源代码中不可见匿名内部类本质上是非静态内部类的一种特殊形式因此同样持有外部类引用。4.2、内存泄漏风险由于非静态内部类持有外部类引用容易导致内存泄漏public class Activity extends AppCompatActivity { // ❌ 错误非静态内部类持有Activity引用 private class MyHandler extends Handler { Override public void handleMessage(Message msg) { // 处理消息 } } // ✅ 正确使用静态内部类 WeakReference private static class MyStaticHandler extends Handler { private WeakReferenceActivity activityRef; MyStaticHandler(Activity activity) { activityRef new WeakReference(activity); } Override public void handleMessage(Message msg) { Activity activity activityRef.get(); if (activity ! null) { // 处理消息 } } } }4.3、kotlin嵌套类/内部类的设计上有重要区别Java的规则默认的嵌套类不加static 非静态内部类 → 持有外部类引用加static的嵌套类 静态内部类 → 不持有外部类引用Kotlin的规则默认的嵌套类 静态内部类 → 不持有外部类引用加inner关键字的嵌套类 非静态内部类 → 持有外部类引用4.4、Kotlin版本的Handler内存泄漏示例class MyActivity : AppCompatActivity() { // ❌ 错误加inner的内部类持有Activity引用 private inner class MyHandler : Handler() { override fun handleMessage(msg: Message) { // 处理消息 } } // ✅ 正确默认嵌套类静态内部类 WeakReference private class MyStaticHandler(activity: MyActivity) : Handler() { private val activityRef: WeakReferenceMyActivity WeakReference(activity) override fun handleMessage(msg: Message) { activityRef.get()?.let { activity - // 处理消息 } } } }五、函数与函数式编程5.1、lambda表达式val list listOf(1, 2, 3, 4, 5, 6, 7) list.filter { it % 2 1 } 因为filter()函数只有一个参数所有括号被省略了。所以filter()函数调用的完整写法是 list.filter ({ it % 2 1 }) 实际的Lambda 表达 list.filter({ it - it % 2 1 })5.2、个表达式使用let最常用于判空和转换// 1. 判空 (最常用!) user?.let { // 只有 user 不为 null 时才会执行这里 println(User is safe: ${it.name}) // 使用 it 访问 } // 2. 转换 val length Hello.let { println(it) it.length // 返回长度 5赋值给 length }apply最常用于对象初始化场景创建对象后立刻给它的属性赋值// 传统写法 val user User(Tom, 20, Beijing) user.city Shanghai user.age 21 // apply 写法 (更优雅) val user User(Tom, 20, Beijing).apply { city Shanghai // 直接调用属性前面隐含了 this. age 21 } // apply 函数返回的是 user 对象本身所以可以直接赋值run结合了 let 和 apply 的特点场景需要执行一段代码块这段代码块依赖于某个对象并且最后需要返回一个计算结果而不是对象本身。val user User(Tom, 20, Beijing) val resultString user.run { city London // 修改属性 age 30 User ${name} moved to $city // 最后一行是返回值 } println(resultString) // 输出: User Tom moved to Londonalso用于顺便做某事场景在链式调用中不想打断流程但又想顺便打印个日志或做个校验。它返回对象本身所以不影响后面的操作val numbers mutableListOf(one, two, three) numbers .also { println(添加前: $it) } // 顺便打印一下列表当前状态 .add(four)