《Kotlin核心编程》上篇

基础语法

基础语法、类型推导、变量与函数声明、高阶函数、Lambda 表达式、流程控制以及字符串操作等主要知识点。这些内容是 Kotlin 编程的基础。

类型推导

Kotlin 具有强大的类型推导能力,在变量声明时如果初始值已经明确,类型可以省略不写。编译器会根据初始值自动推导变量类型。

Kotlin 复制代码
val number = 10 // 编译器自动推导 number 为 Int 类型
val message = "Hello, Kotlin" // 自动推导为 String 类型

变量声明

val 声明的变量:一旦赋值不能再重新赋值,类似 Java 中的 final 变量,但更加简洁。var 声明的变量:可以在后续代码中重新赋值。

Kotlin 复制代码
// val 声明的变量不可重新赋值
val PI: Double = 3.1415926
// PI = 3.14  // 这行代码会报错,因为 PI 是不可变的

// var 声明的变量可重新赋值
var count: Int = 0
count = 10

函数声明

Kotlin 中函数声明使用 fun 关键字,语法形式为 fun 函数名(参数列表): 返回类型 { 函数体 }。如果函数体只有一行代码,可以使用表达式函数体的形式。

Kotlin 复制代码
// 常规函数声明
fun add(a: Int, b: Int): Int {
    return a + b
}

// 表达式函数体
fun multiply(a: Int, b: Int): Int = a * b

// 无返回值函数
fun printMessage(message: String): Unit {
    println(message)
}

高阶函数

高阶函数是指可以接受函数作为参数,或者返回一个函数的函数。在 Kotlin 中,函数是一等公民,可以像其他数据类型一样进行传递和操作。

Kotlin 复制代码
// 高阶函数,接受一个函数作为参数
fun operate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
    return operation(a, b)
}

// 定义一个用于传递给高阶函数的普通函数
fun subtract(a: Int, b: Int): Int = a - b

fun main() {
    val result1 = operate(5, 3, ::subtract)
    println("Subtraction result: $result1")

    // 使用 Lambda 表达式作为参数传递给高阶函数
    val result2 = operate(5, 3) { x, y -> x + y }
    println("Addition result: $result2")
}

Lambda表达式

Lambda 表达式是一种简洁的匿名函数,它可以作为表达式传递给高阶函数。其语法形式为 { 参数列表 -> 函数体 }

Kotlin 复制代码
// 使用 Lambda 表达式作为函数参数
val numbers = listOf(1, 2, 3, 4, 5)
val sum = numbers.fold(0) { acc, num -> acc + num }
println("Sum of numbers: $sum")

// Lambda 表达式作为返回值
fun createAdder(): (Int) -> Int {
    return { number -> number + 10 }
}

fun main() {
    val adder = createAdder()
    val result = adder(5)
    println("Result of adding 10 to 5: $result")
}

表达式和流程控制

Kotlin 提供了常见的流程控制语句,如 if - elsewhenforwhile 等。其中,if 表达式在 Kotlin 中可以作为表达式返回值,而不仅仅是语句。

Kotlin 复制代码
// if - else 作为表达式
val max = if (5 > 3) 5 else 3
println("Max value: $max")

// when 表达式
val number = 3
val description = when (number) {
    1 -> "One"
    2 -> "Two"
    else -> "Other"
}
println("Description of $number: $description")

// for 循环
for (i in 1..5) {
    println(i)
}

// while 循环
var index = 0
while (index < 5) {
    println(index)
    index++
}

字符串操作

Kotlin 提供了丰富的字符串操作函数,如拼接、格式化、查找、替换等。字符串模板是 Kotlin 中一个非常实用的特性,可以在字符串中直接嵌入变量。

Kotlin 复制代码
// 字符串拼接
val firstName = "John"
val lastName = "Doe"
val fullName = "$firstName $lastName"
println("Full name: $fullName")

// 字符串格式化
val age = 30
val message = "My name is $firstName and I'm $age years old."
println(message)

// 字符串查找
val text = "Hello, Kotlin"
val containsKotlin = text.contains("Kotlin")
println("Does the text contain 'Kotlin'? $containsKotlin")

// 字符串替换
val newText = text.replace("Kotlin", "World")
println("New text: $newText")

面向对象

Kotlin类和接口

Kotlin 类
  • 定义与构造函数:Kotlin 中类的定义使用 class 关键字。类可以有主构造函数和次构造函数。主构造函数是类头的一部分,直接跟在类名之后。如果主构造函数没有任何注解或者可见性修饰符,可以省略 constructor 关键字。
Kotlin 复制代码
class Person(val name: String, var age: Int) {
    // 主构造函数参数直接声明为属性
    init {
        println("A person named $name is created.")
    }

    // 次构造函数
    constructor(name: String) : this(name, 0) {
        println("A person named $name with age 0 is created.")
    }
}
  • 成员属性与方法:类可以包含属性和方法。属性有 val(只读)和 var(读写)两种类型。方法的定义与普通函数类似,使用 fun 关键字。
Kotlin 复制代码
class Circle(val radius: Double) {
    val area: Double
        get() = Math.PI * radius * radius

    fun circumference(): Double = 2 * Math.PI * radius
}
Kotlin 接口
  • 定义与实现:接口使用 interface 关键字定义,接口可以包含抽象方法和非抽象方法(需有默认实现)。类通过 : 符号实现接口。
Kotlin 复制代码
interface Shape {
    fun area(): Double
    fun perimeter(): Double {
        // 非抽象方法,有默认实现
        return 0.0
    }
}

class Rectangle(val width: Double, val height: Double) : Shape {
    override fun area(): Double = width * height
    override fun perimeter(): Double = 2 * (width + height)
}

Kotlin的修饰符

  • 类修饰符:

    • public:默认修饰符,类、属性和方法对所有调用者可见。

    • private:类、属性或方法仅在声明它们的文件或类内部可见。

    • protected:与 private 类似,但在子类中也可见。

    • internal:类、属性或方法在相同模块内可见

Kotlin 复制代码
class Outer {
    private val privateProperty = "Private"
    protected val protectedProperty = "Protected"
    internal val internalProperty = "Internal"
    public val publicProperty = "Public"

    private fun privateMethod() = "This is private"
    protected fun protectedMethod() = "This is protected"
    internal fun internalMethod() = "This is internal"
    public fun publicMethod() = "This is public"
}

class Inner : Outer() {
    fun accessProperties() {
        // 可以访问 protectedProperty
        println(protectedProperty)
        // 不能访问 privateProperty
        // println(privateProperty)
    }
}
  • 属性修饰符:除了上述可见性修饰符外,还有 lateinit 用于延迟初始化属性,const 用于声明编译时常量属性。小问题:lateinit var如何保证使用时一定被初始化?解决方案:1.在使用前进行非空判断,在使用 lateinit var 变量之前,通过 ::variable.isInitialized;2.在构造函数或 init 块中初始化。3.在方法中严格按照顺序初始化。
Kotlin 复制代码
class MyClass {
    lateinit var lateinitVar: String

    fun initLateinitVar() {
        lateinitVar = "Initialized"
    }

    companion object {
        const val CONSTANT_VALUE = 10
    }
}

多继承问题

传统面向对象语言中类不能同时继承多个父类,这会导致菱形继承问题。Kotlin 通过接口来解决类似问题,一个类可以实现多个接口,接口可以有默认方法实现。虽然这不是严格意义上的多继承,但在一定程度上提供了类似功能,同时避免了菱形继承的复杂性。

Kotlin 复制代码
interface Flyable {
    fun fly() = println("I can fly")
}

interface Swimmable {
    fun swim() = println("I can swim")
}

class Duck : Flyable, Swimmable

数据类

数据类使用 data 关键字定义,主要用于保存数据。Kotlin 会自动为数据类生成 equals()hashCode()toString()copy() 以及解构声明所需的函数。

Kotlin 复制代码
data class User(val name: String, val age: Int)

fun main() {
    val user1 = User("Alice", 25)
    val user2 = User("Alice", 25)
    println(user1 == user2) // 自动生成的 equals 方法比较内容,输出 true
    println(user1) // 自动生成的 toString 方法,输出 User(name=Alice, age=25)
    val (name, age) = user1 // 解构声明
    println("$name is $age years old")
    val user3 = user1.copy(age = 26) // 使用 copy 方法创建新对象
    println(user3)
}

object

  • 对象声明:使用 object 关键字可以声明一个单例对象,它在第一次被访问时初始化,且在整个应用程序生命周期内只有一个实例。
Kotlin 复制代码
object Logger {
    fun log(message: String) = println("Log: $message")
}

fun main() {
    Logger.log("This is a log message")
}
  • 伴生对象:在类内部使用 companion object 声明的对象,它可以包含类似于 Java 中静态成员的内容。伴生对象的成员可以通过类名直接访问。
Kotlin 复制代码
class MathUtils {
    companion object {
        fun add(a: Int, b: Int): Int = a + b
    }
}

fun main() {
    val result = MathUtils.add(3, 5)
    println("Result of addition: $result")
}
  • 对象表达式:用于创建匿名对象,可实现接口或继承类。
Kotlin 复制代码
val runnable = object : Runnable {
    override fun run() {
        println("Running in a new thread")
    }
}
Thread(runnable).start()

代数数据类型和模式匹配

数据类型

  • 基本数据类型

    • 数值类型:Kotlin 有多种数值类型,如 Byte(8 位)、Short(16 位)、Int(32 位)、Long(64 位)、Float(32 位浮点数)、Double(64 位浮点数)。与 Java 不同,Kotlin 的数值类型是对象,有相应的成员函数。例如,123.toDouble() 可将 Int 转换为 Double

    • 字符类型:Char 用于表示单个字符,用单引号括起来,如 'a'。字符不能直接当作数字使用,但可以通过 toInt() 等方法转换。

    • 布尔类型:Boolean 只有两个值 truefalse,用于逻辑判断。

  • 可空类型

    • Kotlin 通过在类型后面加 ? 来表示可空类型,如 String?。这有助于在编译时检测空指针异常。

    • 访问可空类型变量的方法或属性时,需要进行空值检查。可以使用安全调用操作符 ?.,如 nullableString?.length,如果 nullableStringnull,表达式返回 null,而不会抛出空指针异常。

Kotlin 复制代码
var nullableString: String? = "Hello"
nullableString = null
  • 类型别名

    • 可以使用 typealias 为现有类型定义别名,提高代码的可读性和维护性。例如:
Kotlin 复制代码
typealias MyLong = Long 
val myNumber: MyLong = 1234567890123456789L

模式匹配

  • when 表达式与模式匹配

    • when 表达式在 Kotlin 中功能强大,不仅可以用于替代 switch - case,还支持模式匹配。例如:
Kotlin 复制代码
fun describe(obj: Any) = when (obj) {
    is String -> "It's a string with length ${obj.length}"
    is Int -> "It's an integer"
    else -> "Unknown type"
}
//这里的 is 关键字用于判断对象是否为某种类型,从而执行相应分支。
  • 解构声明

    • 解构声明允许将一个对象分解为多个变量。例如,对于一个包含两个元素的 Pair

    • 对于自定义类,如果类提供了 componentN() 函数(N 从 1 开始),也可以使用解构声明。例如:

Kotlin 复制代码
val pair = Pair(1, "two")
val (first, second) = pair
println("$first, $second")

data class Point(val x: Int, val y: Int)
val point = Point(10, 20)
val (x, y) = point
println("$x, $y")
  • 密封类与模式匹配

    • 密封类的作用:1.表示受限的类继承结构,所有子类都在同一文件中定义;2.与 when 表达式配合实现安全的模式匹配;3.增强代码的可读性和可维护性:保证了 when 表达式覆盖了所有可能的 Result 子类。例如:
Kotlin 复制代码
sealed class Result
class Success(val data: String) : Result()
class Failure(val error: String) : Result()

fun handleResult(result: Result) = when (result) {
    is Success -> println("Success: ${result.data}")
    is Failure -> println("Failure: ${result.error}")
}
相关推荐
FunnySaltyFish6 小时前
什么?Compose 把 GapBuffer 换成了 LinkBuffer?
算法·kotlin·android jetpack
Kapaseker12 小时前
Compose 进阶—巧用 GraphicsLayer
android·kotlin
Kapaseker1 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
A0微声z3 天前
Kotlin Multiplatform (KMP) 中使用 Protobuf
kotlin
alexhilton4 天前
使用FunctionGemma进行设备端函数调用
android·kotlin·android jetpack
lhDream4 天前
Kotlin 开发者必看!JetBrains 开源 LLM 框架 Koog 快速上手指南(含示例)
kotlin
RdoZam4 天前
Android-封装基类Activity\Fragment,从0到1记录
android·kotlin
Kapaseker5 天前
研究表明,开发者对Kotlin集合的了解不到 20%
android·kotlin
糖猫猫cc5 天前
Kite:两种方式实现动态表名
java·kotlin·orm·kite
如此风景5 天前
kotlin协程学习小计
android·kotlin