Kotlin 习题集 · 进阶篇

Kotlin 习题集 · 进阶篇

涵盖面向对象、扩展、Lambda、泛型、协程基础等核心进阶内容。


第一章 面向对象编程

1.1 类与构造器

题目: 定义一个 User 类,包含:

  • 属性:name (只读)、age (可变)、email (默认 "unknown")
  • 主构造器直接初始化属性
  • 在主构造器中添加校验:age 必须 >= 0

答案:

kotlin 复制代码
class User(
    val name: String,
    var age: Int,
    val email: String = "unknown"
) {
    init {
        require(age >= 0) { "Age must be non-negative" }
    }
}

fun main() {
    val user = User("Alice", 25)
    println("${user.name}, ${user.age}, ${user.email}")  // Alice, 25, unknown
    
    user.age = 30
    println(user.age)  // 30
    
    // user.name = "Bob"  // 编译错误,val 不可修改
    
    // val invalid = User("Bob", -1)  // 运行时异常
}

1.2 次构造器与委托

题目: 定义 Person 类,使用主构造器初始化 name,次构造器接受 age 并委托给主构造器。

答案:

kotlin 复制代码
class Person(val name: String) {
    var age: Int = 0
    
    constructor(name: String, age: Int) : this(name) {
        this.age = age
    }
    
    constructor(name: String, age: Int, city: String) : this(name, age) {
        println("Created: $name, $age, $city")
    }
}

fun main() {
    val p1 = Person("Alice")
    println("${p1.name}, age=${p1.age}")  // Alice, age=0
    
    val p2 = Person("Bob", 30)
    println("${p2.name}, age=${p2.age}")  // Bob, age=30
    
    Person("Carol", 25, "Beijing")
}

1.3 延迟初始化

题目: 定义一个 Database 类,使用 lateinit 延迟初始化 connection,在 connect() 方法中赋值。

答案:

kotlin 复制代码
class Database {
    lateinit var connection: String
    
    fun connect() {
        connection = "Connected to database"
    }
    
    fun isConnected(): Boolean {
        return ::connection.isInitialized
    }
}

fun main() {
    val db = Database()
    println(db.isConnected())  // false
    
    db.connect()
    println(db.isConnected())  // true
    println(db.connection)      // Connected to database
}

1.4 数据类

题目: 定义 Point 数据类,包含 x, y,实现:

  1. 创建两个点,使用 copy 复制并修改 y
  2. componentN 解构
  3. 测试 equals / hashCode / toString

答案:

kotlin 复制代码
data class Point(val x: Int, val y: Int)

fun main() {
    val p1 = Point(1, 2)
    val p2 = Point(1, 2)
    
    println(p1)                          // Point(x=1, y=2)
    println(p1 == p2)                    // true
    println(p1.hashCode() == p2.hashCode())  // true
    
    // copy 并修改
    val p3 = p1.copy(y = 10)
    println(p3)  // Point(x=1, y=10)
    
    // 解构
    val (a, b) = p1
    println("a=$a, b=$b")  // a=1, b=2
    
    // 用于集合
    val points = listOf(Point(1,2), Point(3,4))
    println(points.toString())  // [Point(x=1, y=2), Point(x=3, y=4)]
}

1.5 枚举类

题目: 定义 Color 枚举(RED, GREEN, BLUE),添加 rgb 属性返回颜色对应的 RGB 值。实现根据名称查找颜色。

答案:

kotlin 复制代码
enum class Color(val rgb: Int) {
    RED(0xFF0000),
    GREEN(0x00FF00),
    BLUE(0x0000FF);
    
    fun hex() = "#%06X".format(rgb)
}

fun main() {
    println(Color.RED.rgb)   // 16711680
    println(Color.GREEN.hex())  // #00FF00
    
    // 遍历
    Color.values().forEach { 
        println("${it.name} = ${it.hex()}")
    }
    
    // 通过名称查找
    val color = Color.valueOf("BLUE")
    println(color)  // BLUE
    
    // 与 when 配合(穷举检查)
    fun getColorName(c: Color) = when (c) {
        Color.RED -> "红色"
        Color.GREEN -> "绿色"
        Color.BLUE -> "蓝色"
    }
    println(getColorName(Color.RED))  // 红色
}

1.6 嵌套类与内部类

题目: 定义 Outer 类包含嵌套类 Nested 和内部类 Inner,说明它们的区别。

答案:

kotlin 复制代码
class Outer {
    val outerVal = "outer"
    
    class Nested {
        // 嵌套类不能访问外部类的成员
        fun greet() = "Hello from Nested"
    }
    
    inner class Inner {
        // 内部类可以访问外部类的成员
        fun greet() = "Hello from Inner, outerVal=$outerVal"
    }
}

fun main() {
    // 嵌套类直接通过外部类访问
    println(Outer.Nested().greet())  // Hello from Nested
    
    // 内部类需要外部类实例
    val outer = Outer()
    println(outer.Inner().greet())  // Hello from Inner, outerVal=outer
}

1.7 对象表达式与 object 声明

题目: 使用 object 声明单例 Config,使用对象表达式实现临时接口。

答案:

kotlin 复制代码
// 单例对象
object Config {
    val host = "localhost"
    val port = 8080
    
    fun info() = "Config: $host:$port"
}

fun main() {
    println(Config.info())  // Config: localhost:8080
    
    // 对象表达式:临时实现接口
    val listener = object : Runnable {
        override fun run() {
            println("Running!")
        }
    }
    listener.run()  // Running!
    
    // 带状态的对象表达式
    var counter = 0
    val inc = object {
        fun add() { counter++ }
        fun get() = counter
    }
    inc.add()
    println(inc.get())  // 1
}

1.8 伴生对象

题目:Person 类添加 companion object,实现工厂方法 create 和常量 MAX_AGE

答案:

kotlin 复制代码
class Person(val name: String, val age: Int) {
    companion object {
        const val MAX_AGE = 150
        const val MIN_AGE = 0
        
        // 工厂方法
        fun create(name: String, age: Int): Person {
            return Person(name, age.coerceIn(MIN_AGE, MAX_AGE))
        }
        
        // 便捷工厂
        fun createAdult(name: String) = Person(name, 18)
        
        // 可以实现接口
        interface Factory {
            fun create(): Person
        }
    }
}

fun main() {
    val p = Person.create("Alice", 200)
    println("${p.name}, ${p.age}")  // Alice, 150 (被限制)
    
    val adult = Person.createAdult("Bob")
    println("${adult.name}, ${adult.age}")  // Bob, 18
    
    // 通过类名直接访问伴生对象成员
    println(Person.MAX_AGE)  // 150
}

第二章 继承与接口

2.1 抽象类

题目: 定义抽象类 Shape,包含抽象属性 area 和抽象方法 draw()。实现 CircleRectangle 子类。

答案:

kotlin 复制代码
abstract class Shape {
    abstract val area: Double
    abstract fun draw(): String
    
    // 抽象类可以有非抽象方法
    fun description() = "Shape with area: $area"
}

class Circle(val radius: Double) : Shape() {
    override val area: Double get() = Math.PI * radius * radius
    
    override fun draw() = "Circle(radius=$radius)"
}

class Rectangle(val width: Double, val height: Double) : Shape() {
    override val area: Double get() = width * height
    
    override fun draw() = "Rectangle(${width}x${height})"
}

fun main() {
    val shapes = listOf(Circle(5.0), Rectangle(4.0, 6.0))
    shapes.forEach {
        println("${it.draw()}, area=${"%.2f".format(it.area)}")
        // Circle(radius=5.0), area=78.54
        // Rectangle(4.0x6.0), area=24.00
    }
}

2.2 接口

题目: 定义接口 FlyableSwimmable,实现 Duck 类同时实现两个接口。

答案:

kotlin 复制代码
interface Flyable {
    fun fly(): String
    val maxAltitude: Int get() = 1000  // 接口可以有默认属性
}

interface Swimmable {
    fun swim(): String
}

class Duck(val name: String) : Flyable, Swimmable {
    override fun fly() = "$name is flying at alt ${maxAltitude}m"
    
    override fun swim() = "$name is swimming"
    
    // 实现多个接口时,如果方法冲突必须明确覆盖
    fun show() {
        println(fly())
        println(swim())
    }
}

fun main() {
    val duck = Duck("Donald")
    duck.show()
    
    // 接口引用
    val f: Flyable = duck
    println(f.fly())  // Donald is flying at alt 1000m
    
    val s: Swimmable = duck
    println(s.swim())  // Donald is swimming
}

2.3 接口与抽象类的选择

题目: 说明以下场景应选择接口还是抽象类:

  1. PrintableDocumentImage 实现打印
  2. VehicleEngineWheel 作为组成部分
  3. Comparable 让不同类型实现比较

答案:

kotlin 复制代码
// 场景1 & 3: 接口更适合(行为契约,无状态)
interface Printable {
    fun print()
}

interface Comparable<T> {
    fun compareTo(other: T): Int
}

// 场景2: 组合优于继承,但抽象类可用于"是"关系
// 如果所有 Vehicle 都有引擎和轮子,可用抽象类
abstract class Vehicle {
    abstract val engine: String
    abstract val wheelCount: Int
}

class Car : Vehicle() {
    override val engine = "V8"
    override val wheelCount = 4
}

// 关键区别:
// - 接口:无状态,多实现,Java 8+ 支持 default 方法
// - 抽象类:有状态,单继承,适合"is-a"关系

// 示例:Comparable 接口
data class Person(val name: String, val age: Int) : Comparable<Person> {
    override fun compareTo(other: Person) = age - other.age
}

fun main() {
    println(Person("Alice", 30) > Person("Bob", 25))  // true
}

2.4 方法覆盖规则

题目: 定义父类 Base 有方法 foo(),子类 Derived 覆盖它。使用 super 调用父类实现。

答案:

kotlin 复制代码
open class Base {
    open fun foo() = "Base.foo()"
    fun bar() = "Base.bar()"
}

class Derived : Base() {
    override fun foo() = "Derived.foo()"
    
    fun callSuper() = super.foo()
}

fun main() {
    val d = Derived()
    println(d.foo())          // Derived.foo()
    println(d.callSuper())    // Base.foo()
    println(d.bar())          // Base.bar()
    
    // 多态
    val b: Base = Derived()
    println(b.foo())          // Derived.foo() (运行时多态)
    println(b.bar())          // Base.bar()
}

第三章 扩展与高阶函数

3.1 扩展函数

题目:String 类添加扩展函数 addExclamation,将感叹号添加到字符串末尾;添加扩展属性 lastChar

答案:

kotlin 复制代码
fun String.addExclamation(): String = this + "!"

// 扩展属性
val String.lastChar: Char
    get() = this[length - 1]

fun main() {
    println("Hello".addExclamation())  // Hello!
    println("Kotlin".lastChar)         // n
    
    // 可空 receiver
    fun String?.orEmpty(): String = this ?: ""
    val nullStr: String? = null
    println(nullStr.orEmpty())  // (空字符串)
}

3.2 扩展函数实战

题目:List<Int> 添加扩展函数:

  1. sumOfDigits() - 返回所有数字(假设元素是多位整数)的位数总和
  2. average() - 自定义平均值(实现与标准库相同功能)

答案:

kotlin 复制代码
fun List<Int>.sumOfDigits(): Int {
    return this.sumOf { kotlin.math.abs(it).toString().length }
}

// 例如 [12, 3, 456] -> 位数: 2 + 1 + 3 = 6

fun List<Int>.customAverage(): Double {
    return if (isEmpty()) 0.0 else sum().toDouble() / size
}

fun main() {
    println(listOf(12, 3, 456).sumOfDigits())  // 6
    println(listOf(1, 2, 3, 4).customAverage())  // 2.5
    
    // 链式调用
    println(listOf(10, 20, 30).map { it * 2 }.customAverage())  // 40.0
}

3.3 Lambda 表达式基础

题目: 将以下匿名函数转换为 Lambda 表达式:

kotlin 复制代码
val add = fun(x: Int, y: Int): Int = x + y
val square = fun(x: Int): Int = x * x

答案:

kotlin 复制代码
// Lambda 表达式语法
val add: (Int, Int) -> Int = { x, y -> x + y }
val square: (Int) -> Int = { it * it }  // 单参数可用 it

fun main() {
    println(add(3, 4))      // 7
    println(square(5))      // 25
    
    // 高阶函数中使用 Lambda
    val list = listOf(1, 2, 3, 4, 5)
    
    // 完整语法
    list.forEach({ x: Int -> println(x) })
    
    // 最后参数可移到括号外
    list.forEach { x -> println(x) }
    
    // 单参数可用 it
    list.forEach { println(it) }
    
    // 多参数 Lambda
    val map = mapOf("a" to 1, "b" to 2)
    map.forEach { (k, v) -> println("$k -> $v") }
}

3.4 高阶函数

题目: 定义高阶函数 applyIf,接受值和条件函数,仅当条件为真时执行转换函数。

答案:

kotlin 复制代码
fun <T, R> T.applyIf(predicate: (T) -> Boolean, transform: (T) -> R): R? {
    return if (predicate(this)) transform(this) else null
}

fun main() {
    val result1 = 10.applyIf({ it > 5 }, { it * 2 })
    println(result1)  // 20
    
    val result2 = 3.applyIf({ it > 5 }, { it * 2 })
    println(result2)  // null
    
    // 字符串示例
    val s = "Kotlin"
    val upper = s.applyIf({ it.length > 3 }, { it.uppercase() })
    println(upper)  // KOTLIN
    
    // 结合 let
    val nullable: String? = null
    val processed = nullable?.applyIf({ it.length > 3 }, { it.uppercase() })
    println(processed)  // null
}

3.5 inline 函数

题目: 解释为什么 repeat 是内联函数,定义一个简化版 myRepeat

答案:

kotlin 复制代码
// 内联函数:编译器将函数调用替换为函数体,避免 Lambda 带来的开销
inline fun myRepeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
        action()
    }
}

// noinline: 不内联 Lambda 参数
inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) {
    println("Calling inlined:")
    inlined()
    println("Calling not inlined:")
    notInlined()
}

// crossinline: 确保 Lambda 不允许非局部返回
inline fun bar(crossinline action: () -> Unit) {
    println("Before")
    action()  // 不能使用 return
    println("After")
}

fun main() {
    myRepeat(3) {
        println("Hello")  // 打印3次
    }
    
    // 内联的代价:代码膨胀,但性能更好(尤其在循环中)
}

第四章 泛型

4.1 泛型类与函数

题目: 定义泛型 Box<T> 类,存储单一值;定义泛型函数 swap,交换数组中两个位置的元素。

答案:

kotlin 复制代码
class Box<T>(var content: T) {
    override fun toString() = "Box($content)"
}

fun <T> swap(arr: Array<T>, i: Int, j: Int) {
    val temp = arr[i]
    arr[i] = arr[j]
    arr[j] = temp
}

fun main() {
    val box = Box("Hello")
    println(box)  // Box(Hello)
    box.content = "World"
    println(box)  // Box(World)
    
    val arr = arrayOf(1, 2, 3, 4)
    swap(arr, 0, 3)
    println(arr.toList())  // [4, 2, 3, 1]
    
    // 类型约束
    fun <T : Comparable<T>> maxOf(a: T, b: T): T = if (a > b) a else b
    println(maxOf(5, 3))  // 5
    println(maxOf("apple", "banana"))  // banana
}

4.2 泛型约束

题目: 定义函数 sumOfList,约束 T 必须为 Number 子类,返回元素总和。

答案:

kotlin 复制代码
fun <T : Number> sumOfList(list: List<T>): Double {
    return list.sumOf { it.toDouble() }
}

fun main() {
    println(sumOfList(listOf(1, 2, 3)))           // 6.0
    println(sumOfList(listOf(1.5, 2.5, 3.5)))      // 7.5
    println(sumOfList(listOf(1, 2.5, 3)))         // 6.5
    
    // 多个约束
    fun <T> saveToCache(item: T) where T : Any, T : Comparable<T> {
        println("Saving $item")
    }
    saveToCache("Hello")
    // saveToCache(null)  // 编译错误,约束 T : Any 排除 null
}

4.3 协变与逆变

题目: 解释 out(协变)和 in(逆变)的使用场景,定义 Producer<out T>Consumer<in T>

答案:

kotlin 复制代码
// 协变:T 只出现在输出位置(生产)
interface Producer<out T> {
    fun produce(): T
    // fun consume(item: T)  // 编译错误,不能在输入位置使用 T
}

// 逆变:T 只出现在输入位置(消费)
interface Consumer<in T> {
    fun consume(item: T)
    // fun produce(): T  // 编译错误,不能在输出位置使用 T
}

// 不变:两者皆有
interface Container<T> {
    fun get(): T
    fun put(item: T)
}

class Food
class Apple : Food()

class FoodProducer : Producer<Food> {
    override fun produce() = Food()
}

class AppleProducer : Producer<Apple> {
    override fun produce() = Apple()
}

fun main() {
    // Producer<Apple> 可赋值给 Producer<Food>(协变)
    val producer: Producer<Food> = AppleProducer()
    println(producer.produce())
    
    // Consumer<Food> 可赋值给 Consumer<Apple>(逆变)
    val consumer: Consumer<Apple> = FoodProducer()
    consumer.consume(Apple())
}

4.4 泛型擦除与 reified

题目: 说明类型擦除的影响,定义 reified 内联函数实现在运行时获取泛型类型。

答案:

kotlin 复制代码
// 类型擦除:运行时不保留泛型信息
class Container<T> {
    // 在运行时会变成 Object
}

fun <T> printType Erasure() {
    // println(T::class)  // 编译错误,擦除后无法获取
}

// reified:内联函数保留泛型类型信息
inline fun <reified T> printType() {
    println(T::class.simpleName)
}

inline fun <reified T> isInstanceOf(value: Any): Boolean {
    return value is T
}

fun main() {
    printType<String>()  // String
    printType<Int>()    // Int
    
    println(isInstanceOf<String>("hello"))  // true
    println(isInstanceOf<String>(123))       // false
    
    // 应用:创建实例
    inline fun <reified T> create(): T = T::class.java.getDeclaredConstructor().newInstance() as T
}

第五章 协程基础

5.1 协程构建器

题目: 使用 launchasyncrunBlocking 创建协程,说明它们的区别。

答案:

kotlin 复制代码
import kotlinx.coroutines.*

fun main() = runBlocking {
    // launch: 异步执行,不返回结果,fire-and-forget
    val job = launch {
        delay(100)
        println("Launch done")
    }
    
    // async: 返回结果,Deferred<T>
    val deferred = async {
        delay(200)
        42
    }
    
    println("Result: ${deferred.await()}")  // 等待并获取结果
    
    job.join()  // 等待 launch 完成
    println("All done")
}

// 区别:
// - launch: 不返回结果,用于"执行并忘记"任务
// - async: 返回 Deferred,适合并行执行并收集结果
// - runBlocking: 阻塞当前线程直到协程完成(仅用于 main 或测试)

5.2 挂起函数

题目: 定义挂起函数 fetchUserfetchOrders,并行获取后组合输出。

答案:

kotlin 复制代码
import kotlinx.coroutines.*

suspend fun fetchUser(): String {
    delay(100)  // 模拟网络延迟
    return "Alice"
}

suspend fun fetchOrders(): List<String> {
    delay(150)
    return listOf("Order1", "Order2", "Order3")
}

fun main() = runBlocking {
    // 顺序执行
    val start = System.currentTimeMillis()
    val user = fetchUser()
    val orders = fetchOrders()
    println("Sequential: ${System.currentTimeMillis() - start}ms")  // ~250ms
    
    // 并行执行
    val start2 = System.currentTimeMillis()
    val userDeferred = async { fetchUser() }
    val ordersDeferred = async { fetchOrders() }
    
    println("User: ${userDeferred.await()}")
    println("Orders: ${ordersDeferred.await()}")
    println("Parallel: ${System.currentTimeMillis() - start2}ms")  // ~150ms
}

5.3 协程上下文与调度器

题目: 使用不同调度器运行协程:

  1. Dispatchers.Default - CPU 密集型
  2. Dispatchers.IO - IO 密集型
  3. Dispatchers.Main - UI 线程(Android)

答案:

kotlin 复制代码
import kotlinx.coroutines.*

fun main() = runBlocking {
    // CPU 密集型:默认调度器(共享线程池,核心数)
    launch(Dispatchers.Default) {
        println("Default: ${Thread.currentThread().name}")
    }
    
    // IO 密集型:IO 调度器(大量线程)
    launch(Dispatchers.IO) {
        println("IO: ${Thread.currentThread().name}")
    }
    
    // 单线程调度器:确保顺序执行
    val single = Dispatchers.newSingleThreadContext("my-thread")
    launch(single) {
        println("Single: ${Thread.currentThread().name}")
    }.join()
    
    // 切换上下文
    launch(Dispatchers.Default) {
        println("Before: ${Thread.currentThread().name}")
        
        withContext(Dispatchers.IO) {
            println("Switched: ${Thread.currentThread().name}")
        }
        
        println("Back: ${Thread.currentThread().name}")
    }
}

5.4 结构化并发

题目: 使用 coroutineScopesupervisorScope 实现结构化并发,理解作用域取消。

答案:

kotlin 复制代码
import kotlinx.coroutines.*

fun main() = runBlocking {
    // coroutineScope: 子协程失败会导致整个作用域取消
    try {
        coroutineScope {
            launch {
                delay(100)
                println("Task 1 done")
            }
            launch {
                delay(50)
                throw RuntimeException("Task 2 failed!")
            }
        }
    } catch (e: Exception) {
        println("Scope cancelled: ${e.message}")  // Task 2 failed!
    }
    
    // supervisorScope: 子协程失败不会影响兄弟协程
    supervisorScope {
        launch {
            delay(100)
            println("Task A done")  // 仍会执行
        }
        launch {
            delay(50)
            throw RuntimeException("Task B failed!")
        }
    }
    println("Supervisor scope survived")
    
    // 取消
    val job = launch {
        repeat(1000) { i ->
            println("Task $i")
            delay(100)
        }
    }
    
    delay(350)
    println("Cancelling...")
    job.cancel()
    job.join()
    println("Cancelled")
}

5.5 Flow 基础

题目: 使用 flow 创建数据流,实现冷流、背压和取消。

答案:

kotlin 复制代码
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun numbersFlow(): Flow<Int> = flow {
    for (i in 1..5) {
        delay(100)
        emit(i)
    }
}

fun main() = runBlocking {
    // 冷流:只有 collect 时才会执行
    val flow = numbersFlow()
    
    launch {
        flow.collect { println("Collector1: $it") }
    }
    
    delay(50)
    
    // 背压:使用 buffer / collect
    launch {
        numbersFlow()
            .buffer()  // 缓冲,避免发射阻塞
            .collect { 
                delay(150)  // 处理慢于发射
                println("Slow collector: $it")
            }
    }
    
    // 取消
    withTimeoutOrNull(350) {
        numbersFlow().collect { println("Timeout: $it") }
    }
    
    // 转换操作
    numbersFlow()
        .map { it * it }
        .filter { it > 4 }
        .onEach { println("Before: $it") }
        .launchIn(this)  // 在协程外启动收集
    
    delay(500)
}

第六章 操作符重载

6.1 一元与二元操作符

题目: 为自定义类 Point 重载 +-unaryMinus++ 操作符。

答案:

kotlin 复制代码
data class Point(val x: Int, val y: Int) {
    operator fun plus(other: Point) = Point(x + other.x, y + other.y)
    operator fun minus(other: Point) = Point(x - other.x, y - other.y)
    
    unaryMinus operator fun unaryMinus() = Point(-x, -y)
    
    operator fun inc() = Point(x + 1, y + 1)
}

fun main() {
    val p1 = Point(1, 2)
    val p2 = Point(3, 4)
    
    println(p1 + p2)      // Point(x=4, y=6)
    println(p1 - p2)      // Point(x=-2, y=-2)
    println(-p1)          // Point(x=-1, y=-2)
    
    var p = Point(1, 1)
    println(p++)           // Point(x=1, y=1) (先返回,后++)
    println(p)             // Point(x=2, y=2)
}

6.2 比较与包含操作符

题目:Date 类实现 compareTo,并重载 in 操作符判断日期是否在范围内。

答案:

kotlin 复制代码
data class Date(val year: Int, val month: Int, val day: Int) : Comparable<Date> {
    override fun compareTo(other: Date): Int {
        return when {
            year != other.year -> year - other.year
            month != other.month -> month - other.month
            else -> day - other.day
        }
    }
    
    operator fun rangeTo(other: Date) = DateRange(this, other)
}

class DateRange(val start: Date, val end: Date) {
    operator fun contains(date: Date): Boolean {
        return date >= start && date <= end
    }
}

fun main() {
    val d1 = Date(2024, 1, 1)
    val d2 = Date(2024, 12, 31)
    val check = Date(2024, 6, 15)
    
    println(d1 < d2)  // true
    println(check in d1..d2)  // true
    
    // 也可用于 when 表达式
    when (check.month) {
        in 1..3 -> println("Q1")
        in 4..6 -> println("Q2")
        else -> println("Other")
    }
}

6.3 下标与调用操作符

题目:Matrix 类实现 [] 下标访问和 () 调用操作符。

答案:

kotlin 复制代码
class Matrix(private val data: Array<IntArray>) {
    val rows = data.size
    val cols = data[0].size
    
    operator fun get(row: Int, col: Int): Int = data[row][col]
    
    operator fun set(row: Int, col: Int, value: Int) {
        data[row][col] = value
    }
    
    // 调用操作符
    operator fun invoke(): String {
        return buildString {
            data.forEach { row ->
                appendLine(row.joinToString(" "))
            }
        }
    }
    
    operator fun invoke(row: Int): IntArray = data[row]
}

fun main() {
    val m = Matrix(arrayOf(intArrayOf(1, 2, 3), intArrayOf(4, 5, 6)))
    
    println(m[0, 1])  // 2
    m[0, 1] = 10
    println(m[0, 1])  // 10
    
    println(m())  // 打印矩阵
    
    println(m(1).toList())  // [4, 5, 6](调用第二行)
}

答案汇总索引

章节 题目 核心知识点
1.1-1.8 类与构造器 主/次构造器、lateinit、数据类、枚举、嵌套类、伴生对象
2.1-2.4 继承与接口 抽象类、接口、覆盖规则
3.1-3.5 扩展与高阶 扩展函数/属性、Lambda、inline
4.1-4.4 泛型 泛型类/函数、约束、协变逆变、reified
5.1-5.5 协程 launch/async、挂起函数、调度器、结构化并发、Flow
6.1-6.3 操作符重载 一元/二元操作符、比较操作符、下标操作符

进阶篇结束。准备好进入 高级篇 了吗?

相关推荐
赏金术士1 小时前
Kotlin 习题集 · 基础篇
android·开发语言·kotlin
ch.ju1 小时前
Java程序设计(第3版)第三章——数组的遍历
java·开发语言
何故染尘優1 小时前
面试八股文-01
java·jvm·面试
青春易逝丶1 小时前
JAVA基础面试题
java·开发语言
yyuuuzz1 小时前
企业出海aws运维常见问题梳理
运维·服务器·网络·数据库·aws
Austindatabases1 小时前
数据不准确,数据丢失,SQLite怎么保证计算不丢数--SQLite 五脏俱全系列 (5)
java·开发语言·数据库·sqlite
滑稽之神眷顾者1 小时前
基于正倒排索引的文档搜索引擎测试报告
java·开发语言·功能测试
橙子圆1231 小时前
Redis知识5之持久化
数据库·redis·缓存
霸道流氓气质1 小时前
Spring AI ChatMemory 对话记忆配置指南:概念、实战与常见问题
java·人工智能·spring