知识专区
第087篇 函数类型与 typealias:回调接口的新写法
Kotlin中,函数类型(如`(Int) -> String`)本质是编译为`FunctionN`接口的语法糖,支持型变、空安全与默认值;`typealias`仅为编译期别名,提升可读性但无类型隔离。二者协同,体现“用语言特性而非绕行”的设计哲学。
第086篇 泛型型变 in 与 out:声明处型变
Kotlin型变核心是“位置约束”:`out T`仅用于返回位(协变,只读),`in T`仅用于参数位(逆变,只写);越界即编译报错。`in out T`等价于不变。声明处型变比Java使用处更安全——直接禁用非法操作(如`List<out T>`无`add`)。协程/Flow等API依赖此机制实现类型安全组合。
第085篇 类委托 by:装饰器模式的一行实现
Kotlin类委托`by`是编译期语法糖,自动生成接口抽象方法的转发实现(如`delegate.foo()`),零反射、零运行时开销。但仅支持接口/抽象方法,不委托`Any`三方法、具体类方法及Java默认方法;委托对象天然共享状态,需注意隔离与可变性边界。
第084篇 委托属性与 Delegates:属性系统的深水区
Kotlin委托属性是优雅却常被忽视的特性:编译器将属性读写自动转发至`getValue`/`setValue`方法。本文深入剖析其核心机制,详解`by lazy`、`notNull`、`observable`三大标准委托,并直击Android开发中委托导致内存泄漏、线程不安全等典型坑点与解法。
第083篇 作用域函数五兄弟:let、run、with、apply、also
Kotlin五大作用域函数(`let`/`run`/`with`/`apply`/`also`)本质由两个维度决定:**对象传入方式**(参数`it` vs 接收者`this`)和**返回值类型**(原对象 vs lambda结果)。理解定义即可推导行为,无需死记硬背。`apply`适合配置,`also`专用于链式副作用,`let`/`run`用于变换,`with`是非扩展函数,语义等价`run`。所有函数均为`inline`,需注意`return`语义。
第082篇 reified 泛型:擦除限制的破局者
`reified` 依赖 `inline` 的根本原因是 JVM 泛型擦除——运行期无法获取 `T` 的类型信息。`reified` 并非“恢复”泛型,而是在编译期借助内联,将调用点的实际类型(如 `String`)直接代入函数体,使 `x is T`、`T::class.java` 等操作合法。它仅适用于编译期已知类型,不支持运行时动态类型,且会增加代码体积。工程中应优先使用 AndroidX 官方显式类型 API,必要时提供 `Class<T>` 重载以兼顾灵活性与兼容性。
第081篇 inline 内联函数:高阶函数零开销的秘密
`inline` 本质是编译期函数体展开,消除 Lambda 分配与虚调用,但带来字节码膨胀与方法数增长。需权衡收益:仅对≤10行、纯转发、热路径的薄包装使用。`noinline`(传/存函数)、`crossinline`(禁非局部返回)、`reified`(保留泛型运行时类型)各解特定语义问题。Android 中须警惕 R8 与 dex 65536 限制。
第080篇 Lambda 语法精讲:it、尾随 lambda 与隐式接收者
Kotlin Lambda面试核心在四个易错点:尾随vs括号传参(仅限最后一个参数)、单参隐式`it`与嵌套遮蔽、`return`非局部返回(仅inline函数允许)、块式Lambda返回类型由末行推断。具名参数+inline标注+显式label是避坑关键。
第079篇 高阶函数:函数作为参数与返回值
本文深入解析Android开发中的高阶函数,直击面试痛点:从概念(函数作参数/返回值)到本质(控制反转与流程复用),再到工程落地(生命周期回调、异步回调、DSL作用域函数)。详解性能坑(非inline导致对象分配)、设计误(过度抽象)、内存漏(Lambda捕获this),并给出可落地的修复方案与选型判据。
第068篇 sealed class:状态建模的利器
`sealed class` 是 Kotlin 状态建模的核心工具,本质是“用类型系统表达封闭状态机”。它强制子类同文件/模块定义,使编译器可穷举所有分支,配合 `when` 实现**无 `else` 的完备匹配与类型安全**,彻底杜绝非法状态(如 `loading && data != null`),远超枚举与多字段布尔组合的表达力。
第057篇 设计模式入门:单例、工厂、观察者的 Android 落地
设计模式本质是应对“变化”的解法:封装可变点,降低耦合。Android中,它源于真实痛点——如创建分散、行为需替换、状态需通知等。关键不在背23种名称,而在识别“哪处会因需求变更而反复修改”。单例防多实例、工厂解耦创建、策略隔离算法、观察者实现松耦合通信。用错的根源往往是“为模式而模式”,而非解决真实变化。
第052篇 Socket 与 HTTP:网络编程的两层视角
本文深入解析Android网络底层:Socket(传输层字节流)与HTTP(应用层语义协议)的本质区别及协作关系;聚焦高频面试题——TCP连接池设计、HTTP队头阻塞、TIME_WAIT端口耗尽、TLS握手时机、四层超时分级等;结合OkHttp源码与实战案例,讲清弱网优化、连接复用、缓冲背压与避坑要点。
第051篇 Serializable 与 Parcelable:Android 为什么偏爱后者
Serializable 是 Java 原生序列化机制,依赖反射与字段名对齐,兼容性好但性能差、体积大;Parcelable 是 Android 专用接口,手写定序读写,无反射、零元数据,高效紧凑,但顺序敏感、跨版本易错。Binder 传输必须用 Parcelable——因其面向共享内存、低开销、可控字节布局,而 JSON/Serializable 均无法满足跨进程实时性与缓冲区限制(如 TransactionTooLargeException)。
第063篇 类型推断与基本类型:Kotlin 没有隐式拓宽
Kotlin 用“可空性”统一基本/包装类型:`Int`编译为JVM基本类型,`Int?`才装箱为`Integer`;`==`恒为值比较,算术不隐式提升,需显式`toLong()`等转换;泛型容器仍会装箱。核心是分清语言抽象与JVM现实。
第066篇 lateinit 与 by lazy:延迟初始化的适用边界
`lateinit` 与 `by lazy` 均解决延迟初始化问题,但机制迥异:`lateinit` 是编译期修饰符,仅适用于非基本类型的 `var`,未赋值访问抛异常;`by lazy` 是线程安全的委托,支持所有类型,首次访问才执行初始化。二者适用场景不同,优先考虑 DI、View Binding 等更安全方案。
第048篇 常见垃圾回收器:从 CMS 到 G1 的演进思路
本文深入剖析JVM垃圾回收器的演进本质——并非技术堆砌,而是“吞吐↔停顿”的持续取舍:Serial(小堆低开销)、Parallel(高吞吐/长停顿)、CMS(并发降停顿但碎片/弃用)、G1(Region收益优先/可控停顿)、ZGC/Shenandoah(亚毫秒停顿/吞吐略损)。强调选型需匹配堆规模与业务指标,核心在理解分配速率、存活率与停顿目标的联动关系。
第046篇 类加载机制与双亲委派:热修复的伏笔
类加载机制核心是“双亲委派”——加载请求逐级**上抛**至Bootstrap加载器,确保核心类可信、避免重复加载、保障类唯一性(全限定名+加载器)。它解决安全与一致性问题,而非单纯流程;破坏委派(如SPI、热修复)是设计特性,非错误。面试重在理解动机与权衡。
第078篇 Sequence 与惰性求值:大数据量集合优化
`Sequence` 的核心是**惰性求值**(操作延迟至终端才执行)与**冷流语义**(每次遍历都重新计算,不缓存)。它省内存(无中间集合),但不支持多次遍历、随机访问;适用于大集合多级过滤或无限序列截断(如 `take`)。慎用于副作用操作、未截断的无限流及需重复消费场景——应物化(`toList()`)或内联使用。
第056篇 新时间 API:LocalDateTime 取代 Date 的理由
移动端时间处理易出线上事故:`SimpleDateFormat` 静态共享致线程不安全;跨时区“昨天”判断偏差;字符串截取本地化日期失效。Java 8 `java.time` 核心在于厘清**三类时间语义**:`Instant`(UTC瞬时点)、`LocalDateTime`(无时区墙上时间)、`ZonedDateTime`(含时区规则,支持夏令时)。存储用 `Instant`,展示才绑定时区;格式化必传 `Locale`;`YYYY`≠`yyyy`;`Period`(日历量)与 `Duration`(物理量)不可混用。
第059篇 建造者模式:链式调用为何无处不用在哪些地方
建造者模式核心是**将复杂对象的创建过程外置、分步可控、集中校验**。它解决参数过多、互斥依赖、分步初始化问题,关键在于:私有构造、链式setter、build()统一校验、产物不可变(final+防御拷贝)、默认值内聚于Builder——非仅为语法糖,而是工程化构造控制。
第074篇 区间与遍历:until、downTo 与 step
Kotlin区间与遍历深度解析:`1..10` 创建`IntRange`对象(有内存开销),而`until`/`downTo`/`step`等被编译器优化为零对象计数循环;推荐`0 until size`替代`0..size-1`,避免空集合越界;`downTo`需显式`step -1`防死循环;区间仅用于索引,勿`map`/`filter`滥用。
第071篇 顶层函数与属性:为什么不再需要 Utils 类
Kotlin顶层函数/属性是“语法糖”,编译后归入以文件名命名的静态文件类(如`StringsKt`)。`@file:JvmName`可自定义Java调用类名,`@JvmField`使属性变为真正静态字段,`const val`为编译期常量。核心原则:顶层只放无状态纯函数;可变状态须收敛至`object`,确保修改点可控。
第047篇 垃圾回收基础:可达性分析与 GC Roots
本文深入剖析JVM垃圾回收核心——可达性分析机制,厘清GC Roots四类(栈变量、静态字段、JNI引用、活跃线程)作为泄漏排查入口;对比引用计数缺陷,详解强/软/弱/虚四级引用的本质差异在于“回收时机”;直击Android开发中静态缓存、Context泄漏等高频坑点,并给出支配树定位、显式限容、弱引用替代等工程化解决方案。
第050篇 IO 流体系:字节流与字符流的分层设计
Java IO流是面试分水岭:字节流处理二进制,字符流处理文本(内部仍转字节);装饰器模式实现缓冲、数据/对象序列化等能力。核心考点:缓冲区优化原理、字符编码陷阱(必须显式指定UTF-8)、try-with-resources资源管理、批量读写避坑。真实项目中,用错流类型、忽略编码、未关闭流是高频故障源。
第064篇 空安全入门:?、!! 与 ?. 的三分天下
Kotlin空安全是编译期类型契约:`T`与`T?`本质不同。`?.`链式短路不求值,`?:`右值懒执行,`?.let`中`it`为非空类型,`!!`仅限框架保证场景。核心原则——null是需显式处理的分支,可空性应在数据入口收敛。
第076篇 集合三大类与只读可变两套体系
Kotlin集合分List/Set/Map三组,各含只读与可变类型(共6种)。关键在于:“只读”是类型约束(禁止调用修改方法),≠“不可变”(底层数据仍可能被改)。`listOf()`返回真不可变实现,安全共享;而`asList()`是活视图,需警惕副作用。工程中应坚持“内部可变、对外只读+`toList()`拷贝”。
第053篇 Lambda 与函数式接口:Android 开发的日常语法
本文深入剖析Java Lambda与函数式接口的本质:从匿名内部类演进而来,依托`invokedynamic`与`LambdaMetafactory`实现运行时链接;详解四大核心接口(`Function`/`Consumer`/`Supplier`/`Predicate`)、捕获语义、泛型擦除及Android兼容坑点,强调“行为参数化”思想而非语法糖。
第055篇 Optional 与空值处理:比判空更优雅的表达
`Optional<T>` 是 Java 8 引入的容器类,核心价值是**将“可能为空”显式表达在类型中**,提升空安全与可读性。仅限用作**方法返回值**,禁用于字段、参数及高频路径;需搭配 `ofNullable`、`map`/`flatMap`、`orElseGet` 等规范使用,避免序列化、性能与语义陷阱。
第045篇 JVM 内存区域:堆、栈、方法区与程序计数器
JVM内存区域是面试分水岭:非死记硬背,而要理解线程私有(栈、PC计数器、本地方法栈)与共享(堆、元空间)的本质差异,能据OOM类型精准定位根因——栈溢出看调用链、堆OOM析对象引用、元空间OOM查类加载、直接内存OOM盯NIO缓冲。
第060篇 Java 阶段面试通关地图:六十个考点串联复盘
“Java阶段面试”不是考知识点记忆,而是考察机制理解、场景落地与工程权衡。本文以五条主线(集合、并发、JVM、异常、新特性)为地图,强调“结论+机制+场景+代价”四层回答法,直击HashMap树化、线程池调优、Android-JVM差异等高频深水区,助你从背题党蜕变为真懂原理的工程师。
第065篇 Elvis 运算符与 let:空值处理的组合拳
Kotlin 中 `?:`(Elvis)与 `let` 是被低估却极富表现力的空安全利器:`?:` 是懒求值表达式,专用于优雅兜底或提前返回;`let` 是内联作用域函数,在非空时以参数形式安全处理值。二者常组合为 `x?.let { ... } ?: default`,将“有则处理、无则兜底”升华为可组合、可读、零开销的声明式逻辑。关键在理解求值时机与意图选型——缺失用 `?:`,非空处理用 `let`,状态语义复杂时请用 sealed class 显式建模。
第075篇 when 表达式:比 switch 强在哪里
Kotlin 的 `when` 是强大表达式,远超 Java `switch`:支持值、区间、类型、集合、任意条件五种分支;具备智能转换、顺序匹配、穷举检查(对 sealed/enum 编译期报错);作为表达式需覆盖所有路径,慎用空 `else`。核心价值:将分支逻辑结构化、可赋值、可审查。
第061篇 Kotlin 与 Java 的关系:同一 JVM 上的两门语言
Kotlin与Java互操作≠对称兼容!核心差异在混编边界:平台类型致空安全失效、`internal`编译为public、默认参数需`@JvmOverloads`、data class字段private final使Gson反序列化失配。真功夫在收尾——注解规范、ProGuard保留元数据、协程作用域管控。
第058篇 单例模式六种写法:线程安全与懒加载的平衡
单例模式是面试高频考点,六种写法各具特点:饿汉式线程安全但非懒加载;懒汉式需同步;DCL需`volatile`防重排;静态内部类最推荐(JVM类初始化锁保障懒加载与线程安全);枚举天然防反射与序列化。Android中优先用静态内部类,持Context时务必用`getApplicationContext()`,避免内存泄漏。
第054篇 Stream 常用操作:map、filter 与 collect 实战
Java 8 Stream 是面向数据处理的惰性流水线,由数据源、中间操作(如filter/map)和终端操作(如collect/forEach)组成。惰性求值、短路机制与状态操作是理解关键;并行流仅在大数据量+重计算+无共享状态时才提效。简历写“熟悉”远不如答清“何时不该用”。
第073篇 字符串模板与原生字符串:多行文本的正确姿势
Kotlin字符串模板核心三点:①编译后转为`StringBuilder.append`链(全常量时优化为字面量);②原生字符串`"""..."""`保留缩进,必须用`trimIndent()`或`trimMargin()`清理;③Android中禁在循环内用模板拼接,否则触发O(n²)性能坑。安全上,模板不用于SQL/URL等需解析的场景。
第070篇 扩展函数原理:它到底是不是给类加方法
Kotlin扩展函数本质是**静态方法**,编译后以接收者为首个参数,置于文件类中;调用依**静态类型决议**,不参与多态,**不访问private成员**,且**成员方法永远优先于同名扩展**——它是语法糖,而非真正的方法增强。
第069篇 object 与 companion object:Kotlin 里的单例
本文深入剖析 `object` 与 `companion object` 的本质差异:二者虽均为单例,但字节码结构、初始化时机及 Java 可见性截然不同。`object` 编译为私有静态实例(饿汉式),而 `companion object` 是宿主类内的静态 `Companion` 实例,其初始化绑定类加载。`@JvmStatic` 和 `@JvmField` 不提升性能,而是改变 Java 调用形态与反射可见性。核心警示:慎用 `object` 持有可变状态,伴生对象避免耗时初始化——正确选型应基于作用域需求,而非便利性。
第072篇 中缀表达式与运算符重载:可读性的双刃剑
Kotlin运算符重载比Java更彻底:不仅支持`+ - * /`等映射为`plus`/`minus`等约定函数,还允许任意单参函数通过`infix`声明实现中缀调用(如`a to b`)。核心原则是——符号语义必须与原始含义一致(`+`即相加,`-`即取反或相减),滥用将损害可读性。
第049篇 JVM 调优入门:从 OOM 日志倒推问题
JVM调优核心是方法论而非参数背诵:先分类(堆/元空间/直接内存/栈OOM)、再取证(GC日志/内存快照/线程栈)、接着定性(泄漏 or 配置不足)、最后动参。顺序错则掩盖问题,盲目调大堆只会延迟OOM。Android需额外关注堆分区、largeHeap及meminfo诊断。
第077篇 集合操作符链:filter、map 与 fold
本文深入剖析 Kotlin 集合操作符(`map`/`filter`/`flatMap`/`groupBy`)的**真实性能成本**:每次调用均创建新集合、遍历全量数据。重点揭示“何时不该用”——如十万级数据链式调用致内存暴增、GC 频繁、UI 卡顿;详解三大优化路径:①调整顺序(`filter`前置)、②惰性化(`asSequence`)、③削平链路(`mapNotNull`/`for`),并明确选型依据。
第062篇 val 与 var:不可变优先的工程哲学
`val` 与 `var` 是 Kotlin 不可变性设计的基石:`val` 仅保证**引用不可重绑定**,不约束对象内部状态(如 `val list = mutableListOf()` 仍可 `add`);`var` 允许引用变更。真正安全需结合只读类型(`List`)、`toList()` 拷贝、不可变数据类及并发原语——默认用 `val`,变则审慎用 `var`。
第043篇 CAS 与原子类:无锁编程的第一课
CAS是Compare-And-Swap的缩写,一种硬件级原子指令,实现“比较并交换”的乐观并发控制。它通过volatile保证可见性、CAS保证原子性,但存在ABA问题(用AtomicStampedReference加版本号解决)、高竞争下自旋耗CPU(LongAdder分段累加优化)及仅支持单变量更新等局限。
第042篇 CountDownLatch 与 CyclicBarrier:等待与协作
本文深入解析`CountDownLatch`、`CyclicBarrier`与`Semaphore`的核心差异与实战陷阱:前者为一次性事件门闩,后者为可复用集合点,`Semaphore`则基于独占模式限流。重点剖析“计数未归零阻塞”“屏障损坏”“许可泄漏”等生产级坑点,并给出`finally`防护、超时兜底、参与方一致性等落地解法,助你面试直击采分关键。
第040篇 volatile:可见性、有序性与禁止重排
`volatile` 是Java轻量级同步机制,核心解决**可见性**与**有序性**(靠内存屏障实现),但**不保证原子性**。典型适用:状态标志、引用发布、DCL单例;禁用场景:`count++`、多变量一致性、检查后动作——这些须用原子类或锁。
第044篇 ThreadLocal 原理:主线程到底能不能用
ThreadLocal核心在于“线程独享+弱引用Key+强引用Value”:每个线程持独立ThreadLocalMap,Key为ThreadLocal弱引用,Value强引用用户对象;若不显式remove,线程池复用时易致内存泄漏与数据串号。务必在finally中清理!
第039篇 synchronized 原理:对象头、锁升级与重量级锁
`synchronized` 底层依托对象头 Mark Word 与 `monitorenter` 指令,锁随竞争升级:无锁 → 偏向锁(JDK15 已废弃)→ 轻量级锁(CAS 自旋)→ 重量级锁(ObjectMonitor + 内核阻塞)。`wait` 必在同步块内调用,确保条件检查与等待原子性。
第041篇 线程池七参数:ThreadPoolExecutor 从配置到调优
Android面试高频题“线程池七参数”,实为三层能力筛选:背参数(入门)、讲流程(进阶)、析设计(高手)。核心在于理解`corePoolSize→workQueue→maximumPoolSize→RejectedExecutionHandler`的执行链与制约关系,避开无界队列、线程命名缺失、拒绝策略误用等典型坑。真懂者必知:参数非独立旋钮,而是协同约束。
第038篇 Thread 与 Runnable:线程生命周期全解
Thread与Runnable本质是“任务”与“执行单元”的分离:Runnable仅定义要做的事(无返回、不抛检异常),Thread负责调度执行(含状态、优先级、生命周期控制)。`start()`才真正启新线程,`run()`只是普通方法调用。常见坑包括误调`run`导致伪并发、异常静默终止、持有Activity引发内存泄漏。工程中应优先使用线程池而非裸Thread。
第028篇 LinkedList 与 ArrayList 选型:随机访问与插删的权衡
LinkedList与ArrayList选型关键在读写特征:ArrayList随机访问O(1),适合读多写少;LinkedList仅两端增删O(1),但按索引操作需遍历O(n),且节点开销大、缓存不友好。工程中默认选ArrayList,除非明确需双端队列语义。