NipGeihou's blog NipGeihou's blog
  • Java

    • 开发规范
    • 进阶笔记
    • 微服务
    • 快速开始
    • 设计模式
  • 其他

    • Golang
    • Python
    • Drat
  • Redis
  • MongoDB
  • 数据结构与算法
  • 计算机网络
  • 应用

    • Grafana
    • Prometheus
  • 容器与编排

    • KubeSphere
    • Kubernetes
    • Docker Compose
    • Docker
  • 组网

    • TailScale
    • WireGuard
  • 密码生成器
  • 英文单词生成器
  • 常用软件
  • Git仓库推荐
🍳烹饪
🧑‍💻关于
  • 分类
  • 标签
  • 归档

NipGeihou

我见青山多妩媚,料青山见我应如是
  • Java

    • 开发规范
    • 进阶笔记
    • 微服务
    • 快速开始
    • 设计模式
  • 其他

    • Golang
    • Python
    • Drat
  • Redis
  • MongoDB
  • 数据结构与算法
  • 计算机网络
  • 应用

    • Grafana
    • Prometheus
  • 容器与编排

    • KubeSphere
    • Kubernetes
    • Docker Compose
    • Docker
  • 组网

    • TailScale
    • WireGuard
  • 密码生成器
  • 英文单词生成器
  • 常用软件
  • Git仓库推荐
🍳烹饪
🧑‍💻关于
  • 分类
  • 标签
  • 归档
  • Kotlin - 入门
    • 创建项目
    • Main入口
    • 语法
      • 变量
      • 字符串模板
      • 基本类型
      • 集合
      • List
      • Set
      • Map
      • 控制流
      • if
      • when(类switch)
      • for
      • While
    • 函数
      • 命名入参
      • 默认参数
      • 无返回值
      • 单行表达式函数
      • Lambda 表达式
    • 对象编程
      • 定义
      • 构造函数
      • 访问属性
      • 成员函数
      • 数据类
    • Null值安全机制
      • 使用安全的调用方式
      • Elvis 运算符
    • 扩展函数
    • 作用域函数
      • let(类匿名函数)
      • apply(初始化对象)
      • run(初始化对象)
      • also
      • with
  • Kotlin
NipGeihou
2026-08-12
目录

Kotlin - 入门

# 创建项目

在 IDEA 中新建项目,选择: Kotlin (项目):

  • 构建系统:Gradle
  • JDK:尽可能新的
  • Gradle DSL:Kotlin

# Main 入口

fun main() {
    println("Hello, world!")
    // Hello, world!
}

# 语法

# 变量

// 只读变量(类似于js的const)
val popcorn = 5    // There are 5 boxes of popcorn
val hotdog = 7     // There are 7 hotdogs

// 可变变量(与js的var同理)
var customers = 10 // There are 10 customers in the queue

// Some customers leave the queue
customers = 8
println(customers)
// 8

# 字符串模板

参考:字符串 | Kotlin 文档 --- Strings | Kotlin Documentation (opens new window)

val customers = 10
println("There are $customers customers")
// There are 10 customers

println("There are ${customers + 1} customers")
// There are 11 customers

# 基本类型

// 整型
val year: Int = 2020
val amount: Long = 350_000_000

// 无符号整型
val score: UInt = 100u

// 浮点数
val currentTemp: Float = 24.5f
val price: Double = 19.99

// 布尔值
val isEnabled: Boolean = true

// 字符
val separator: Char = ','

// 字符串
val message: String = "Hello, world!"

声明一个变量而不对其进行初始化:

val d: Int

# 集合

# List

// 只读列表(类似于数组)
val readOnlyShapes = listOf("triangle", "square", "circle")
println(readOnlyShapes)
// [triangle, square, circle]

// 可变列表(类似于arrayList)
val shapes: MutableList<String> = mutableListOf("triangle", "square", "circle")
println(shapes)
// [triangle, square, circle]

Casting (铸造) 将可变列表变成只读列表;下述 Set、Map 同理

val shapes: MutableList<String> = mutableListOf("triangle", "square", "circle")
val shapesLocked: List<String> = shapes

# Set

// Read-only set
val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry")
// Mutable set with explicit type declaration
val fruit: MutableSet<String> = mutableSetOf("apple", "banana", "cherry", "cherry")

println(readOnlyFruit)
// [apple, banana, cherry]

# Map

// Read-only map
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu)
// {apple=100, kiwi=190, orange=100}

// Mutable map with explicit type declaration
val juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(juiceMenu)
// {apple=100, kiwi=190, orange=100}

# 控制流

# if

val d: Int
val check = true

if (check) {
    d = 1
} else {
    d = 2
}

println(d)
// 1

# when (类 switch)

val obj = "Hello"

when (obj) {
    // Checks whether obj equals to "1"
    "1" -> println("One")
    // Checks whether obj equals to "Hello"
    "Hello" -> println("Greeting")
    // Default statement
    else -> println("Unknown")     
}
// Greeting
val obj = "Hello"    

val result = when (obj) {
    // If obj equals "1", sets result to "one"
    "1" -> "One"
    // If obj equals "Hello", sets result to "Greeting"
    "Hello" -> "Greeting"
    // Sets result to "Unknown" if no previous condition is satisfied
    else -> "Unknown"
}
println(result)
// Greeting
fun main() {
    val trafficLightState = "Red" // This can be "Green", "Yellow", or "Red"

    val trafficAction = when (trafficLightState) {
        "Green" -> "Go"
        "Yellow" -> "Slow down"
        "Red" -> "Stop"
        else -> "Malfunction"
    }

    println(trafficAction)  
    // Stop
}

更多 when 语法参考文档

# for

for (number in 1..5) { 
    // number is the iterator and 1..5 is the range
    print(number)
}
// 12345
val cakes = listOf("carrot", "cheese", "chocolate")

for (cake in cakes) {
    println("Yummy, it's a $cake cake!")
}
// Yummy, it's a carrot cake!
// Yummy, it's a cheese cake!
// Yummy, it's a chocolate cake!

# While

var cakesEaten = 0
while (cakesEaten < 3) {
    println("Eat a cake")
    cakesEaten++
}
// Eat a cake
// Eat a cake
// Eat a cake
var cakesEaten = 0
var cakesBaked = 0
while (cakesEaten < 3) {
    println("Eat a cake")
    cakesEaten++
}
do {
    println("Bake a cake")
    cakesBaked++
} while (cakesBaked < cakesEaten)
// Eat a cake
// Eat a cake
// Eat a cake
// Bake a cake
// Bake a cake
// Bake a cake

# 函数

fun sum(x: Int, y: Int): Int {
    return x + y
}

fun main() {
    println(sum(1, 2))
    // 3
}

# 命名入参

类似于 python 的入参定义,可更改入参顺序

fun printMessageWithPrefix(message: String, prefix: String) {
    println("[$prefix] $message")
}

fun main() {
    // Uses named arguments with swapped parameter order
    printMessageWithPrefix(prefix = "Log", message = "Hello")
    // [Log] Hello
}

# 默认参数

fun printMessageWithPrefix(message: String, prefix: String = "Info") {
    println("[$prefix] $message")
}

fun main() {
    // Function called with both parameters
    printMessageWithPrefix("Hello", "Log") 
    // [Log] Hello
    
    // Function called only with message parameter
    printMessageWithPrefix("Hello")        
    // [Info] Hello
    
    printMessageWithPrefix(prefix = "Log", message = "Hello")
    // [Log] Hello
}

# 无返回值

没有声明返回类型的,则返回类型(隐式)为 Unit

fun printMessage(message: String) {
    println(message)
    // `return Unit` or `return` is optional
}

fun main() {
    printMessage("Hello")
    // Hello
}

# 单行表达式函数

fun sum(x: Int, y: Int) = x + y

fun main() {
    println(sum(1, 2))
    // 3
}

# Lambda 表达式

// 一般写法
fun uppercaseString(text: String): String {
    return text.uppercase()
}
fun main() {
    println(uppercaseString("hello"))
    // HELLO
}

// Lambda 写法
fun main() {
    val upperCaseString = { text: String -> text.uppercase() }
    println(upperCaseString("hello"))
    // HELLO
}

示例 1:过滤

val numbers = listOf(1, -2, 3, -4, 5, -6)

val positives = numbers.filter ({ x -> x > 0 })

val isNegative = { x: Int -> x < 0 }
val negatives = numbers.filter(isNegative)

println(positives)
// [1, 3, 5]
println(negatives)
// [-2, -4, -6]

示例 2:映射

val numbers = listOf(1, -2, 3, -4, 5, -6)
val doubled = numbers.map { x -> x * 2 }

val isTripled = { x: Int -> x * 3 }
val tripled = numbers.map(isTripled)

println(doubled)
// [2, -4, 6, -8, 10, -12]
println(tripled)
// [3, -6, 9, -12, 15, -18]

# 对象编程

# 定义

// class header(类头)声明属性:在类名后的()中定义
class Contact(val id: Int, var email: String) // 声明类属性时,可以在末尾使用逗号
class Contact(val id: Int, var email: String = "[email protected]")

// class body(类体)声明属性:在{}体中定义
class Contact(val id: Int, var email: String) {
    val category: String = ""
}
  • 官方建议属性声明为只读( val ),除非需要在创建类的实例后更改它们

# 构造函数

  • 默认情况下,Kotlin 会自动创建一个构造函数,其参数为 class header 中声明的
  • 无需 new 关键字
class Contact(val id: Int, var email: String)

fun main() {
    val contact = Contact(1, "[email protected]")
}

# 访问属性

在实例名称后添加句点  .  ,然后写出属性名称

class Contact(val id: Int, var email: String)

fun main() {
    val contact = Contact(1, "[email protected]")
    
    // Prints the value of the property: email
    println(contact.email)           
    // [email protected]

    // Updates the value of the property: email
    contact.email = "[email protected]"
    
    // Prints the new value of the property: email
    println(contact.email)           
    // [email protected]
}

扩展知识:也可以字符串模板中使用

println("Their email address is: ${contact.email}")

# 成员函数

在 class body 中定义

class Contact(val id: Int, var email: String) {
    fun printId() {
        println(id)
    }
}

fun main() {
    val contact = Contact(1, "[email protected]")
    // Calls member function printId()
    contact.printId()           
    // 1
}

# 数据类

类似于 Java 中的 Bean 类、模型类、实体类

data class User(val name: String, val id: Int)

kotlin 的类,默认没有继承 Object,因此没有 toString 、 equals 等 Object 类方法

toString

// toString
val user = User("Alex", 1)

// Automatically uses toString() function so that output is easy to read
println(user)            
// User(name=Alex, id=1)

equals

val user = User("Alex", 1)
val secondUser = User("Alex", 1)
val thirdUser = User("Max", 2)

// Compares user to second user
println("user == secondUser: ${user == secondUser}") 
// user == secondUser: true

// Compares user to third user
println("user == thirdUser: ${user == thirdUser}")   
// user == thirdUser: false

Copy

val user = User("Alex", 1)

// Creates an exact copy of user
println(user.copy())       
// User(name=Alex, id=1)

// Creates a copy of user with name: "Max"
println(user.copy("Max"))  
// User(name=Max, id=1)

// Creates a copy of user with id: 3
println(user.copy(id = 3)) 
// User(name=Alex, id=3)

# Null 值安全机制

  • Kotlin 采用了空值安全机制。该机制能在编译时检测  null  值可能存在的问题,而无需等到程序运行时再发现。
  • 默认下所有类型都不能为 null,必须定义,如果需要为 null ,则在类型后添加 ?
fun main() {
    // neverNull has String type
    var neverNull: String = "This can't be null"

    // Throws a compiler error
    neverNull = null

    // nullable has nullable String type
    var nullable: String? = "You can keep a null here"

    // This is OK
    nullable = null

    // By default, null values aren't accepted
    var inferredNonNull = "The compiler assumes non-nullable"

    // Throws a compiler error
    inferredNonNull = null

    // notNull doesn't accept null values
    fun strLength(notNull: String): Int {                 
        return notNull.length
    }

    println(strLength(neverNull)) // 18
    println(strLength(nullable))  // Throws a compiler error
}

# 使用安全的调用方式

fun lengthString(maybeString: String?): Int? = maybeString?.length

fun main() { 
    val nullString: String? = null
    println(lengthString(nullString))
    // null
}
person.company?.address?.country

# Elvis 运算符

通过 Elvis 运算符  ?:  检测到  null  值,你可以指定一个默认值来作为返回值

fun main() {
    val nullString: String? = null
    println(nullString?.length ?: 0)
    // 0
}

# 扩展函数

类似于 Java 的类继承,但又不太一样,因为它是直接作用在父类上的。

fun String.bold(): String = "<b>$this</b>"

fun main() {
    // "hello" is the receiver
    println("hello".bold())
    // <b>hello</b>
}
class HttpClient {
    fun request(method: String, url: String, headers: Map<String, String>): HttpResponse {
        // Network code
    }
}

// 扩展常用方法.get .post
fun HttpClient.get(url: String): HttpResponse = request("GET", url, emptyMap())
fun HttpClient.post(url: String): HttpResponse = request("POST", url, emptyMap())

# 作用域函数

Kotlin 总共有五个作用域相关函数:  let  、  apply  、  run  、  also  和  with  。

# let (类匿名函数)

由于 kotlin 有严格的 null 安全机制,因此每次调用函数,都是要添加判空逻辑,kotlin 有 let 语法来处理这一问题。

fun sendNotification(recipientAddress: String): String {
    println("Yo $recipientAddress!")
    return "Notification sent!"
}

fun getNextAddress(): String {
    return "[email protected]"
}

fun main() {
    val address: String? = getNextAddress()
    // Argument type mismatch: actual type is 'String?', but 'String' was expected.
    sendNotification(address)
}

处理:

val address: String? = getNextAddress()
val confirm = address?.let {
    sendNotification(it) //  `it` 来引用 `address` 变量
}

# apply (初始化对象)

  • 传统写法,需要将初始化逻辑和其他逻辑代码混在一块
  • kotlin 的 apply 函数则将初始化的函数单独作用域,提高可读性
class Client() {
    var token: String? = null
    fun connect() = println("connected!")
    fun authenticate() = println("authenticated!")
    fun getData() : String {
        println("getting data!")
        return "Mock data"
    }
}

val client = Client()

fun main() {
    client.token = "asdf"
    client.connect()
    // connected!
    client.authenticate()
    // authenticated!
    client.getData()
    // getting data!
}
val client = Client().apply {
    token = "asdf"
    connect()
    // connected!
    authenticate()
    // authenticated!
}

fun main() {
    client.getData()
    // getting data!
}

# run (初始化对象)

相当于带返回值的 apply

val client: Client = Client().apply {
    token = "asdf"
}

fun main() {
    val result: String = client.run {
        connect()
        // connected!
        authenticate()
        // authenticated!
        getData()
        // getting data!
    }
}

# also

多用于调试

fun main() {
    val medals: List<String> = listOf("Gold", "Silver", "Bronze")
    val reversedLongUppercaseMedals: List<String> =
        medals
            .map { it.uppercase() }
            .filter { it.length > 4 }
            .reversed()
    println(reversedLongUppercaseMedals)
    // [BRONZE, SILVER]
}
fun main() {
    val medals: List<String> = listOf("Gold", "Silver", "Bronze")
    val reversedLongUppercaseMedals: List<String> =
        medals
            .map { it.uppercase() }
            .also { println(it) }
            // [GOLD, SILVER, BRONZE]
            .filter { it.length > 4 }
            .also { println(it) }
            // [SILVER, BRONZE]
            .reversed()
    println(reversedLongUppercaseMedals)
    // [BRONZE, SILVER]
}

# with

class Canvas {
    fun rect(x: Int, y: Int, w: Int, h: Int): Unit = println("$x, $y, $w, $h")
    fun circ(x: Int, y: Int, rad: Int): Unit = println("$x, $y, $rad")
    fun text(x: Int, y: Int, str: String): Unit = println("$x, $y, $str")
}

fun main() {
    val mainMonitorPrimaryBufferBackedCanvas = Canvas()

    mainMonitorPrimaryBufferBackedCanvas.text(10, 10, "Foo")
    mainMonitorPrimaryBufferBackedCanvas.rect(20, 30, 100, 50)
    mainMonitorPrimaryBufferBackedCanvas.circ(40, 60, 25)
    mainMonitorPrimaryBufferBackedCanvas.text(15, 45, "Hello")
    mainMonitorPrimaryBufferBackedCanvas.rect(70, 80, 150, 100)
    mainMonitorPrimaryBufferBackedCanvas.circ(90, 110, 40)
    mainMonitorPrimaryBufferBackedCanvas.text(35, 55, "World")
    mainMonitorPrimaryBufferBackedCanvas.rect(120, 140, 200, 75)
    mainMonitorPrimaryBufferBackedCanvas.circ(160, 180, 55)
    mainMonitorPrimaryBufferBackedCanvas.text(50, 70, "Kotlin")
}
val mainMonitorSecondaryBufferBackedCanvas = Canvas()
with(mainMonitorSecondaryBufferBackedCanvas) {
    text(10, 10, "Foo")
    rect(20, 30, 100, 50)
    circ(40, 60, 25)
    text(15, 45, "Hello")
    rect(70, 80, 150, 100)
    circ(90, 110, 40)
    text(35, 55, "World")
    rect(120, 140, 200, 75)
    circ(160, 180, 55)
    text(50, 70, "Kotlin")
}
上次更新: 2026/08/13, 14:48:29
最近更新
01
React Native - 开始
08-12
02
3D打印机箱IO挡板
07-24
03
增肌与减脂
07-11
更多文章>
Theme by Vdoing | Copyright © 2018-2026 NipGeihou | 友情链接
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式