【安卓開發】Kotlin入門教程

一、Kotlin 基礎入門

1.1 Kotlin 簡介

Kotlin 是一種由 JetBrains 開發的靜態類型編程語言,運行在 Java 虛擬機上,也可以編譯為 JavaScript 或原生代碼。它于 2017 年被 Google 宣布為 Android 官方開發語言。

主要特點:

  • 簡潔:相比 Java 減少約 40% 的樣板代碼

  • 安全:內置空安全機制

  • 互操作:100% 兼容 Java

  • 工具友好:由 JetBrains 開發,IDE 支持完善

1.2 開發環境搭建:Android Studio 配置

  1. Android Studio 3.0+ 已內置 Kotlin 支持

  2. 可通過插件管理器確認 Kotlin 插件狀態

  3. 轉換現有 Java 文件:Code > Convert Java File to Kotlin File

1.3 基本語法結構

1.3.1 Hello World 程序
fun main() {println("Hello, World!")
}

與 Java 對比:

  • 沒有類聲明也能運行

  • 函數使用?fun?關鍵字

  • 分號可選

  • 打印使用?println?而非?System.out.println

1.4 變量與常量

1.4.1 變量聲明
var mutableVar: String = "可變變量"
val immutableVal: Int = 42 // 類似 Java 的 final

類型推斷:

var inferredString = "類型推斷為 String"
val inferredInt = 123 // 推斷為 Int
1.4.2 基本數據類型

Kotlin 中所有數據類型都是對象:

類型位寬示例
Byte8123
Short1612345
Int321234567890
Long64123L
Float32123.45f
Double64123.45
Char16'A'
Boolean-true/false

類型轉換:

val intValue = 42
val longValue = intValue.toLong() // 顯式轉換
1.4.3 字符串模板
val name = "Alice"
println("Hello, $name!") // 簡單變量
println("Name length: ${name.length}") // 表達式

多行字符串:

val text = """|第一行|第二行|第三行
""".trimMargin()

第二章:Kotlin 函數編程

2.1 函數定義

2.1.1 基本函數
fun sum(a: Int, b: Int): Int {return a + b
}
2.1.2 表達式函數體
fun sum(a: Int, b: Int) = a + b
2.1.3 默認參數
fun greet(name: String = "World") {println("Hello, $name!")
}greet() // Hello, World!
greet("Alice") // Hello, Alice!
2.1.4 命名參數
fun createUser(id: Int,name: String,email: String = "",age: Int = 0
) { /*...*/ }// 調用
createUser(id = 1,name = "Alice",age = 25
)

2.2 高階函數

2.2.1 函數作為參數
fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {return operation(a, b)
}val result = calculate(10, 5) { x, y -> x + y }
2.2.2 函數作為返回值
fun getOperation(type: String): (Int, Int) -> Int {return when(type) {"add" -> { a, b -> a + b }"multiply" -> { a, b -> a * b }else -> { _, _ -> 0 }}
}

2.3 Lambda 表達式

基本語法:

val sum = { x: Int, y: Int -> x + y }
println(sum(1, 2)) // 3

帶接收者的 Lambda:

val stringPlus: String.(String) -> String = { this + it }println("Hello".stringPlus("World")) // HelloWorld

2.4 內聯函數

inline fun measureTime(block: () -> Unit) {val start = System.currentTimeMillis()block()println("執行時間: ${System.currentTimeMillis() - start}ms")
}measureTime {// 要測量的代碼
}

三、Kotlin 面向對象編程

3.1 類與對象:Kotlin的核心抽象單元

Kotlin的類系統在保持與Java互操作性的同時,通過精簡的語法顯著提升了開發效率。類的聲明可以包含構造函數、屬性初始化、成員函數等多個部分,但語法比Java更加緊湊。

3.1.1 主構造函數與初始化塊

主構造函數是類頭的一部分,它跟在類名后面,可以包含參數聲明。這些參數不僅用于構造實例,還可以直接聲明為類屬性:

class Person(val name: String,       // 只讀屬性var age: Int,           // 可變屬性gender: String          // 構造函數參數(非屬性)
) {init {require(age > 0) { "年齡必須為正數" }println("創建Person實例: $name")}val genderUpper = gender.uppercase()  // 屬性初始化
}

關鍵點

  • init?塊在對象創建時執行,可以有多個(按聲明順序執行)

  • 主構造函數參數加?val/var?才會成為屬性

  • 屬性可以在類體內直接初始化

3.1.2 次構造函數與默認值

當需要多種構造方式時,可以定義次構造函數。但在Kotlin中,更推薦使用默認參數替代多個構造函數:

class User {constructor(email: String) {// 從email構造}constructor(facebookId: Long) {// 從社交賬號構造}
}// 更Kotlin化的方式(使用默認參數)
class BetterUser(val email: String? = null,val facebookId: Long? = null
) {init {require(email != null || facebookId != null) {"至少需要一種登錄方式"}}
}

3.2 繼承體系:更安全的類擴展機制

Kotlin的繼承系統通過明確的修飾符設計,強制開發者更謹慎地處理繼承關系,避免了Java中常見的繼承濫用問題。

3.2.1 類繼承的基本規則
open class Animal(val name: String) {  // 必須標記open才能被繼承open val sound = "..."            // 必須標記open才能被重寫open fun makeSound() {println(sound)}fun eat() { /* 默認final */ }
}class Cat(name: String) : Animal(name) {override val sound = "Meow"      // 屬性重寫final override fun makeSound() {  // 標記final禁止進一步重寫super.makeSound()println("追加貓特有的行為")}
}

重要特性

  • 默認所有類都是final(與Java相反)

  • 必須顯式使用?open?允許繼承

  • override?關鍵字強制要求顯式標注

  • 支持屬性重寫(而不僅是方法)

3.2.2 初始化順序陷阱

Kotlin的類初始化順序與Java不同,特別是在涉及屬性重寫時:

open class Base(val name: String) {init {println("初始化Base")}open val size: Int = name.length.also {println("初始化Base.size")}
}class Derived(name: String,val lastName: String
) : Base(name.capitalize()) {init {println("初始化Derived")}override val size: Int = (super.size + lastName.length).also {println("初始化Derived.size")}
}// 使用
Derived("hello", "world")

輸出順序

  1. Base的主構造函數參數求值(name.capitalize())

  2. Base的init塊

  3. Base的屬性初始化

  4. Derived的主構造函數參數初始化

  5. Derived的init塊

  6. Derived的重寫屬性初始化

3.3 接口進化:帶有默認實現的契約

Kotlin接口可以包含抽象屬性、抽象方法以及帶有默認實現的方法,比Java 8的接口更靈活:

interface Clickable {val clickable: Boolean    // 抽象屬性fun click()              // 抽象方法fun showOff() = println("我是可點擊的!")  // 默認實現
}interface Focusable {fun showOff() = println("我是可聚焦的!")
}class Button : Clickable, Focusable {override val clickable: Boolean = trueoverride fun click() = println("按鈕被點擊")// 必須解決接口沖突override fun showOff() {super<Clickable>.showOff()super<Focusable>.showOff()}
}

接口特性

  • 支持屬性聲明(但不能保存狀態)

  • 默認方法沖突必須顯式解決

  • 可以實現多個接口

  • 與Java 8接口互操作

3.4 數據類:自動生成樣板代碼的利器

數據類(data class)是Kotlin中用于純粹保存數據的特殊類,編譯器會自動生成以下方法:

  • equals()/hashCode()

  • toString()

  • copy()

  • 解構聲明(componentN()函數)

3.4.1 數據類的限制與技巧
data class Person(val name: String,val age: Int
) {var address: String = ""  // 不會參與equals/hashCode// 自定義copy行為fun copyWithPrefix(prefix: String) = copy(name = "$prefix$name")
}// 使用示例
val person = Person("Alice", 25)
val (name, age) = person  // 解構聲明
val olderAlice = person.copy(age = 30)

重要限制

  • 主構造函數必須至少有一個參數

  • 所有主構造參數必須標記為?val?或?var

  • 不能是?abstractopensealed?或?inner

3.4.2 深度復制與嵌套數據類

對于包含可變引用或嵌套集合的數據類,需要注意淺復制問題:

data class Company(val name: String, val employees: MutableList<Employee>)// 安全復制方式
val newCompany = company.copy(employees = company.employees.toMutableList()
)

3.5 密封類:受限的類層次結構

密封類(sealed class)是枚舉和抽象類的結合體,它限制了子類的可能類型,是實現代數數據類型(ADT)的理想選擇。

3.5.1 密封類的典型應用
sealed class Result<out T> {data class Success<T>(val data: T) : Result<T>()data class Error(val exception: Throwable) : Result<Nothing>()object Loading : Result<Nothing>()
}fun handleResult(result: Result<String>) = when(result) {is Result.Success -> println(result.data)is Result.Error -> println(result.exception)Result.Loading -> println("加載中...")// 不需要else分支,所有情況已覆蓋
}

優勢

  • 編譯時檢查窮盡所有可能類型

  • 保持多態特性(不同于枚舉)

  • 每個子類可以有多個實例(除非定義為object)

  • 完美配合when表達式使用

3.5.2 密封類與枚舉的選擇
特性密封類枚舉類
實例數量子類決定固定數量
狀態攜帶可以攜帶復雜數據通常無狀態或簡單狀態
窮盡檢查支持支持
多態性保持丟失
性能稍低更高

適用場景

  • 需要攜帶不同數據的相關類型 → 密封類

  • 固定數量的簡單常量 → 枚舉

  • 需要模式匹配的場景 → 密封類

3.6 對象聲明與伴生對象:Kotlin的單例模式

Kotlin使用?object?關鍵字實現單例模式,比Java的實現更簡潔安全。

3.6.1 對象聲明的多種用途
// 單例對象
object DatabaseManager {init {println("數據庫連接初始化")}fun query(sql: String) { /*...*/ }
}// 伴生對象(類內部的靜態成員)
class MyClass {companion object Factory {fun create(): MyClass = MyClass()}
}// 對象表達式(匿名對象)
val listener = object : MouseAdapter() {override fun mouseClicked(e: MouseEvent) { /*...*/ }
}

關鍵點

  • 對象聲明是延遲初始化的(首次訪問時初始化)

  • 伴生對象可以命名也可以匿名

  • 伴生對象可以繼承接口

  • JVM上伴生對象成員會生成靜態字段(使用@JvmStatic注解)

3.6.2 伴生對象的進階用法
interface JSONFactory<T> {fun fromJSON(json: String): T
}class Person(val name: String) {companion object : JSONFactory<Person> {override fun fromJSON(json: String): Person {// 解析JSON...return Person(/*...*/)}}
}// 使用
val person = Person.fromJSON(jsonString)

四、Kotlin 高級特性

4.1 擴展函數與屬性

擴展(Extensions)是Kotlin最強大的特性之一,它允許開發者為現有類添加新功能而無需繼承或使用設計模式如裝飾器。這種能力特別適合以下場景:

  • 當你想為第三方庫或SDK中的類添加功能時

  • 需要保持代碼整潔避免工具類泛濫時

  • 希望創建領域特定語言(DSL)時

4.1.1 擴展函數

擴展函數實際上是靜態方法的語法糖。編譯后,擴展函數會被轉換為一個靜態方法,接收者對象作為第一個參數

fun String.addEnthusiasm(amount: Int = 1): String {return this + "!".repeat(amount)
}println("Hello".addEnthusiasm(3)) // Hello!!!

重要注意事項:

  • 擴展函數是靜態解析的,不支持運行時多態

  • 如果擴展函數與成員函數簽名相同,成員函數優先

  • 擴展可以定義在頂層,也可以定義在類內部(作用域受限)

4.1.2 擴展屬性
val String.numberOfVowels: Intget() = count { it.toLowerCase() in setOf('a', 'e', 'i', 'o', 'u') }println("Kotlin".numberOfVowels) // 2

4.2 運算符重載

Kotlin允許通過固定名稱的函數重載數學運算符和比較操作,這使得自定義類型可以像基本類型一樣參與運算,大幅提升代碼可讀性。

data class Point(val x: Int, val y: Int) {operator fun plus(other: Point): Point {return Point(x + other.x, y + other.y)}
}val p1 = Point(1, 2)
val p2 = Point(3, 4)
println(p1 + p2) // Point(x=4, y=6)

4.3 委托

委托(Delegation)是Kotlin實現組合優于繼承原則的核心機制,通過by關鍵字將接口實現委托給其他對象。

4.3.1 類委托的典型應用場景
  1. 裝飾器模式:擴展功能而不修改原類

  2. 接口隔離:將大接口的實現拆分到不同對象

  3. 跨平臺開發:將平臺相關實現委托給具體平臺模塊

4.3.2類委托
interface Database {fun save(data: String)
}class RealDatabase : Database {override fun save(data: String) { /*...*/ }
}class DatabaseProxy(db: Database) : Database by db
4.3.3?屬性委托
import kotlin.properties.Delegatesclass User {var name: String by Delegates.observable("<no name>") {prop, old, new ->println("$old -> $new")}
}val user = User()
user.name = "Alice" // 輸出: <no name> -> Alice
user.name = "Bob"   // 輸出: Alice -> Bob

4.4 泛型

Kotlin的泛型系統在Java基礎上進行了重要改進,解決了類型擦除帶來的諸多限制。

4.4.1 型變注解深度解析
注解位置作用Java對應
out類型參數協變-只作為返回類型? extends
in類型參數逆變-只作為參數類型? super
reified內聯函數保留類型信息
4.4.2 使用
class Box<T>(t: T) {var value = t
}// 使用
val intBox = Box<Int>(1)
val stringBox = Box("String") // 類型推斷

五、Kotlin 協程

5.1 協程基礎

5.1.1 基本概念

協程(Coroutine)本質上是可掛起的計算實例,具有以下核心特點:

  1. 掛起不阻塞:掛起函數會釋放底層線程供其他協程使用

  2. 結構化并發:協程之間存在明確的父子關系

  3. 調度靈活:可在不同線程間自由切換

  4. 資源高效:單個線程可運行數千個協程

5.1.2 協程與線程對比
特性線程協程
創建開銷1MB+ 內存幾十字節
切換成本微秒級納秒級
并發數量數百到數千數百萬
阻塞影響阻塞整個線程僅掛起當前協程
通信機制共享內存+鎖Channel/Flow
5.1.3?基本使用
import kotlinx.coroutines.*fun main() = runBlocking {launch {delay(1000L)println("World!")}println("Hello,")
}

5.2 協程構建器

// launch: 啟動一個不返回結果的協程
val job = launch { /*...*/ }// async: 啟動一個返回 Deferred 結果的協程
val deferred = async { delay(1000L)"Result" 
}
println(deferred.await())// runBlocking: 阻塞當前線程直到協程完成
runBlocking {delay(1000L)
}

5.3 協程上下文與調度器

Dispatchers.Default // CPU 密集型工作
Dispatchers.IO     // IO 密集型工作
Dispatchers.Main   // UI 線程(Android)
Dispatchers.Unconfined // 不限制在任何特定線程// 使用示例
launch(Dispatchers.IO) {// 網絡請求或文件操作
}

5.4 協程取消

val job = launch {repeat(1000) { i ->ensureActive() // 檢查是否取消println("job: I'm sleeping $i ...")delay(500L)}
}
delay(1300L)
job.cancelAndJoin()

六、Kotlin 最佳實踐

6.1 代碼風格

  1. 命名約定:

    • 類/對象:PascalCase

    • 函數/變量:camelCase

    • 常量:UPPER_SNAKE_CASE

  2. 格式化:

    • 4空格縮進

    • 類/函數之間空一行

    • 參數列表過長時換行

6.2 性能優化

  1. 內聯小的高階函數

  2. 避免不必要的對象創建

  3. 使用序列(Sequence)處理大數據集

  4. 注意協程的調度器選擇

6.3 常見陷阱

  1. 空安全:

    val list: List<String> = emptyList()
    val firstItem = list.firstOrNull() // 安全
  2. 相等性:==?對應?equals(),===?檢查引用相等

  3. 初始化順序:
class Example {val a = b + 1 // 錯誤:b 還未初始化val b = 2
}

? ? ??

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/86462.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/86462.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/86462.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

工業機器人保護氣體節約方法

焊接在現代工業生產中作為一項關鍵技術&#xff0c;其效率和質量直接影響著產品的最終性能和生產成本。隨著智能制造的不斷推進&#xff0c;工業焊接機器人在自動化生產線中扮演著越來越重要的角色。焊接過程中的氣體調節一直是一個技術難題&#xff0c;它直接關系到焊接質量的…

java中集合API

集合API 一、簡述二、Collection&#xff08;1&#xff09;.List1.ArrayList&#xff1a;2. LinkedList &#xff08;2&#xff09; Set 三、Map1.HashMap2. TreeMap 三、Iterator接口Collections工具類1.對集合元素進行排序2.基于Comparator&#xff0c;自定義方法(內部類)進行…

Oracle 用戶權限與對象權限詳解

一、權限體系概述 Oracle 數據庫的權限管理是保障數據安全的核心機制&#xff0c;主要分為系統權限&#xff08;System Privileges&#xff09; 和對象權限&#xff08;Object Privileges&#xff09; 兩大類&#xff1a; 系統權限&#xff1a;賦予用戶在數據庫中執行特定操作…

kubectl get pods 時 “client-side throttling, not priority and fairness“ 原因初探

1. 問題起源 在kubernetes里&#xff0c;使用kubectl get pods 時&#xff0c;返回 I0508 05:43:04.655602 100742 request.go:668] Waited for 1.178494016s due to client-side throttling, not priority and fairness, request: GET:https://10.103.0.1:443/apis/cert-ma…

力扣網C語言編程題:位運算來解決 “尋找重復數”

一. 簡介 前面兩篇文章解決力扣網上"查找重復數"的題目&#xff0c;提供了三種思路&#xff1a;哈希表、二分法和快慢指針。文章如下&#xff1a; 力扣網C語言編程題&#xff1a;“尋找重復數”的兩種思路-CSDN博客 力扣網C語言編程題&#xff1a;快慢指針來解決 …

3D視覺感知

目錄 3D視覺感知任務 單目3D感知 單目3D物體檢測 – 直接預測3D信息 單目3D物體檢測 – 總結 單目深度估計 雙目3D感知 多目3D感知 3D視覺感知任務 ? 輸入&#xff1a;單攝像頭或多攝像頭生成的圖像數據 ? 單張圖像 ? 圖像序列 ? 輸出 ? 稀疏&#xff1a…

es中常規的根據字段查詢時走什么索引(說明:「常規的根據字段查詢」不包含分詞查詢)

在Elasticsearch中&#xff0c;“常規的根據字段查詢”且不涉及分詞的查詢&#xff08;如精確匹配、范圍查詢&#xff09;&#xff0c;主要依賴以下索引機制&#xff1a; 一、核心索引類型及適用場景 字段類型索引結構典型查詢方式應用場景keyword倒排索引&#xff08;未分詞…

MYSQL如何插入數據,效率會更高

在MySQL中&#xff0c;插入數據的效率可以通過多種方式逐步提升。以下是從簡單到復雜的優化路徑&#xff0c;幫助你逐步提高數據插入的性能&#xff1a; 一、基礎插入&#xff1a;逐條插入 這是最基礎的插入方式&#xff0c;適用于少量數據的插入操作。雖然簡單&#xff0c;但…

Rabbitmq的五種消息類型介紹,以及集成springboot的使用

交換機類型 Fanout Exchange 扇型交換機&#xff0c;這個交換機沒有路由鍵概念&#xff0c;就算你綁了路由鍵也是無視的。 這個交換機在接收到消息后&#xff0c;會直接轉發到綁定到它上面的所有隊列 Direct Exchange 直連型交換機&#xff0c;根據消息攜帶的路由鍵將消息投遞…

日語學習-日語知識點小記-進階-JLPT-真題訓練-N2階段(4):2022年12月2023年12月

日語學習-日語知識點小記-進階-JLPT-真題訓練-N2階段&#xff08;4&#xff09;&#xff1a;2022年12月&2023年12月 1、前言&#xff08;1&#xff09;情況說明&#xff08;2&#xff09;工程師的信仰&#xff08;3&#xff09;真題訓練 2、2個卷的單詞部分1、 真題-2023年…

從代碼學習深度強化學習 - Actor-Critic 算法 PyTorch版

文章目錄 前言算法原理1. 從策略梯度到Actor-Critic2. Actor 和 Critic 的角色3. Critic 的學習方式:時序差分 (TD)4. Actor 的學習方式:策略梯度5. 算法流程代碼實現1. 環境與工具函數2. 構建Actor-Critic智能體3. 組織訓練流程4. 主程序:啟動訓練5. 實驗結果總結前言 在深…

Python 數據分析與可視化 Day 8 - Pandas 高級操作技巧

? 今日目標 掌握 Pandas 的索引體系&#xff08;Index / MultiIndex&#xff09;使用 set_index() 和 reset_index() 管理數據索引理解 pivot_table 與 melt、stack/unstack 重塑數據形態初步理解“寬表”與“長表”在數據分析與可視化中的應用場景 &#x1f4da; 一、深入理…

Spring Boot整合百度AI人臉比對實戰

目錄 一、簡述 二、依賴 三、代碼步驟 3.1 實體注入 3.2 服務實現 3.3 其它實現 四、小結 歡迎來到 盹貓(>^ω^<)的博客 本篇文章主要介紹了 [Spring Boot整合百度AI人臉比對實戰] ?博主廣交技術好友&#xff0c;喜歡文章的可以關注一下? 一、簡述 人臉識別在日…

使用 pip 安裝 numpy 包卡在 Preparing metadata 階段問題解決

TOC 1 問題描述 使用 pip 安裝numpy卡在下面最后一行的階段&#xff1a; Collecting numpy1.26.4 (from -r requirements.txt (line 2))Using cached https://mirrors.aliyun.com/pypi/packages/65/6e/09db70a523a96d25e115e71cc56a6f9031e7b8cd166c1ac8438307c14058/numpy-…

新手向:Anaconda3的安裝與使用方法

我們在剛開始接觸Python時使用的是Python的直接編譯器,如果我們需要進行其他的項目編寫往往需要使用另一個版本的Python ,這樣反復的下載很是麻煩并且還會造成系統變量的紊亂.這次我們引入Anaconda3,可創建虛擬的Python環境,滿足不同項目的需要,當不用的時候可以直接放心刪除不…

C#中的設計時構造函數

以下是關于設計時構造函數的詳細整理&#xff0c;包括定義、適用場景、相關概念和實際應用&#xff1a; 一、設計時構造函數的定義 設計時構造函數&#xff08;Design-time Constructor&#xff09;是專門為開發工具&#xff08;如Visual Studio、Blazor Designer等&#xff0…

Spring Boot 2.x 項目搭建 (一)

以下是基于Spring Boot 2.x&#xff08;兼容JDK 1.8&#xff09;的項目搭建指南及Markdown文檔生成方案&#xff0c;整合了多個搜索結果中的最佳實踐&#xff1a; 一、項目初始化 1. 使用Spring Initializr創建項目 步驟&#xff1a; 訪問 start.spring.io 或通過IDE&#x…

Kotlin作用域函數:掌握apply/let/run/with/also精髓

一、作用域函數詳解 1. apply&#xff1a;對調用對象進行配置或操作&#xff0c;并返回該對象本身。 接收者引用&#xff1a;this&#xff08;可省略&#xff0c;直接調用接收者成員&#xff09;返回值&#xff1a;接收者對象本身&#xff08;T&#xff09;核心用途&#xff…

Spring Boot監視器:應用監控終極指南

Spring Boot 監視器詳解 Spring Boot 監視器(Monitor)是用于監控和管理 Spring Boot 應用程序運行狀態的核心組件,主要通過 Spring Boot Actuator 和 Spring Boot Admin 兩大工具實現。 一、核心監視器組件 1. Spring Boot Actuator 功能定位:提供應用程序內部運行狀態的原…

SpringBoot 中 @Transactional 的使用

SpringBoot 中 Transactional 的使用 一、Transactional 的基本使用二、Transactional 的核心屬性三、使用避坑&#xff08;失效場景&#xff09;3.1 自調用問題3.2 異常處理不當3.3 類未被 Spring 管理3.4 異步方法內使用失效 四、工作實踐4.1 事務提交之后執行一些操作4.2 事…