当前位置: 首页 > article >正文

《Kotlin核心编程》上篇

基础语法

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

类型推导

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

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

变量声明

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

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

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

函数声明

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

// 常规函数声明
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 中,函数是一等公民,可以像其他数据类型一样进行传递和操作。

// 高阶函数,接受一个函数作为参数
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 表达式是一种简洁的匿名函数,它可以作为表达式传递给高阶函数。其语法形式为 { 参数列表 -> 函数体 }

// 使用 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 中可以作为表达式返回值,而不仅仅是语句。

// 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 中一个非常实用的特性,可以在字符串中直接嵌入变量。

// 字符串拼接
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 关键字。

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 关键字。

class Circle(val radius: Double) {
    val area: Double
        get() = Math.PI * radius * radius

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

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:类、属性或方法在相同模块内可见

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.在方法中严格按照顺序初始化。

class MyClass {
    lateinit var lateinitVar: String

    fun initLateinitVar() {
        lateinitVar = "Initialized"
    }

    companion object {
        const val CONSTANT_VALUE = 10
    }
}

多继承问题

传统面向对象语言中类不能同时继承多个父类,这会导致菱形继承问题。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() 以及解构声明所需的函数。

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 关键字可以声明一个单例对象,它在第一次被访问时初始化,且在整个应用程序生命周期内只有一个实例。

object Logger {
    fun log(message: String) = println("Log: $message")
}

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

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")
}
  • 对象表达式:用于创建匿名对象,可实现接口或继承类。

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,而不会抛出空指针异常。

var nullableString: String? = "Hello"
nullableString = null
  • 类型别名

    • 可以使用 typealias 为现有类型定义别名,提高代码的可读性和维护性。例如:

typealias MyLong = Long 
val myNumber: MyLong = 1234567890123456789L

 

模式匹配

  • when 表达式与模式匹配

    • when 表达式在 Kotlin 中功能强大,不仅可以用于替代 switch - case,还支持模式匹配。例如:

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 开始),也可以使用解构声明。例如:

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 子类。例如:

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}")
}


http://www.kler.cn/a/519480.html

相关文章:

  • vue中onclick如何调用methods中的方法
  • C语言学习强化
  • BLE透传方案,IoT短距无线通信的“中坚力量”
  • Python Flask教程
  • Charles 4.6.7 浏览器网络调试指南:HTTPS抓包(三)
  • 大数据之路:阿里巴巴大数据实践(1)
  • 【动态规划】杨表
  • YOLOv11改进,YOLOv11检测头融合DSConv(动态蛇形卷积),并添加小目标检测层(四头检测),适合目标检测、分割等任务
  • SQL注入漏洞之SQL注入基础知识点 如何检测是否含有sql注入漏洞
  • 【leetcode100】二叉树的层序遍历
  • Elasticsearch中的度量聚合:深度解析与实战应用
  • mock可视化生成前端代码
  • javascript-es6 (一)
  • 【Vim】Vim 中将文件内容复制到系统剪切板的方法
  • 基于Oracle 19C的ADVM与ACFS标准化实施文档
  • Python Pandas数据清洗与处理
  • RabbitMQ---面试题
  • Pyecharts图表交互功能提升
  • vue3+elementPlus之后台管理系统(从0到1)(day4-完结)
  • 在Ubuntu上安装RabbitMQ教程
  • Go语言快速开发入门
  • 微信开发者工具的快捷键
  • ray.rllib-入门实践-12:自定义policy
  • Maui学习笔记-SignalR简单介绍
  • MySQL中的读锁与写锁:概念与作用深度剖析
  • 延迟之争:LLM服务的制胜关键