5 个 demo 帮你理解默认参数、扩展函数、Lambda、闭包、inline 等核心特性。
勾选哪些参数你想"显式传递",看 Kotlin 怎么自动用默认值填补剩下的。
fun connect(
host: String = "localhost",
port: Int = 8080,
timeout: Int = 5000,
useTls: Boolean = false
)
2^4 = 16 个重载方法。
Kotlin 一行函数搞定。
// 必须写工具类
public class StringUtils {
public static String toCamelCase(String s) {
String[] parts = s.split("_");
StringBuilder sb = new StringBuilder();
for (String p : parts) {
sb.append(Character.toUpperCase(p.charAt(0)))
.append(p.substring(1));
}
return sb.toString();
}
}
// 调用 —— 别扭
String r = StringUtils
.toCamelCase("hello_kotlin");
// 直接给 String 类"扩展"方法
fun String.toCamelCase(): String =
this.split("_").joinToString("") {
it.replaceFirstChar { c -> c.uppercase() }
}
// 调用 —— 跟内置方法一样
val r = "hello_kotlin".toCamelCase()
// → "HelloKotlin"
.toCamelCase()
open class A
class B : A()
fun A.hello() = "I am A"
fun B.hello() = "I am B"
val a: A = B()
println(a.hello()) // 输出 "I am A" ← 不是 "I am B"!
// 因为按编译期类型 A 决定调哪个
同一个需求:"把列表里每个元素 ×2"。看从最啰嗦的写法一步步演化到最简洁。
list.map(new Function<Integer, Integer>() {
@Override
public Integer apply(Integer x) {
return x * 2;
}
});
list.map({ x: Int -> x * 2 })
list.map({ x -> x * 2 })
list.map() { x -> x * 2 }
list.map { x -> x * 2 }
list.map { it * 2 }
fun makeCounter(): () -> Int {
var count = 0
return {
count++
count
}
}
val c1 = makeCounter()
val c2 = makeCounter() // 注意:每个 counter 有自己独立的 count
下面是两个独立的 counter,分别记着自己的 count,互不干扰。
每个 counter 都"捕获"了 makeCounter 函数里的 count 变量,但**两份拷贝独立**。
这就是闭包的本质:函数 + 它出生时所在环境的引用。
普通高阶函数每次调用都要创建一个 Function 对象,频繁调用有 GC 压力。inline 让编译器把函数体和 lambda 直接嵌入调用点。
inline fun <T> List<T>.fastForEach(
action: (T) -> Unit
) {
for (item in this) action(item)
}
// 调用
listOf(1, 2, 3).fastForEach {
println(it)
}
// fastForEach 调用消失了,直接展开:
val list = listOf(1, 2, 3)
for (item in list) {
println(item) // ← lambda 也内联了
}
// 没有 Function 对象创建
// 没有方法调用开销