Kotlin 语法入门与快速上手

27 阅读8分钟

Kotlin 语法入门

本文面向 Kotlin 小白,以及从 Java 转过来的 Android 开发。目标不是把 Kotlin 所有语法一次背完,而是让你能快速跑通基础写法,并理解它们为什么常出现在 Android 项目里。

怎么最快跑起来

方式一:Android Studio Scratch

  1. 打开 Android Studio。
  2. 选择 File -> New -> Scratch File -> Kotlin
  3. 粘贴下面代码并运行。
fun main() {
    val name = "Android"
    var count = 1
    count += 1

    println("Hello, $name")
    println("count = $count")
}

方式二:新建一个普通 Kotlin 文件

如果项目已经启用了 Kotlin,可以在 app/src/main/javaapp/src/main/kotlin 下新建 KotlinPractice.kt

package com.example.demo

fun main() {
    println("Kotlin is ready")
}

方式三:在线跑

可以使用 Kotlin Playground,把本文代码块逐个粘贴进去运行。学习语法时,不必一开始就放进 Activity。


1. valvar

基础用法

  • val:只读变量,类似 Java 的 final 引用。
  • var:可变变量,可以重新赋值。
  • Kotlin 推荐优先使用 val,只有确实需要变化时才用 var
fun main() {
    val userName = "Tom"
    var age = 18

    age = 19

    println(userName)
    println(age)
}

Java 对比

final String userName = "Tom";
int age = 18;
age = 19;

Android 常见用法

class MainActivity : AppCompatActivity() {
    private val adapter = UserAdapter()
    private var selectedUserId: Long = -1L
}

adapter 创建后通常不需要换对象,用 valselectedUserId 会随着点击变化,用 var


2. 类型推断

基础用法

Kotlin 很多时候可以根据右边的值推断类型。

val name = "Alice"       // String
val count = 10           // Int
val price = 19.9         // Double
val enabled = true       // Boolean

需要明确类型时,也可以写出来:

val userId: Long = 1001L
val title: String = "Home"

伪代码

如果右侧值能推断类型:
    编译器自动补全变量类型
否则:
    开发者必须显式声明类型

Android 常见用法

val intent = Intent(this, DetailActivity::class.java)
val titleView = findViewById<TextView>(R.id.titleView)

Intent(...) 的返回类型很明确,所以不需要重复写 Intent intent


3. 字符串模板

基础用法

Kotlin 用 $变量名${表达式} 拼接字符串。

fun main() {
    val name = "Kotlin"
    val version = 2

    println("Hello, $name")
    println("next version = ${version + 1}")
}

Java 对比

String name = "Kotlin";
System.out.println("Hello, " + name);

Android 常见用法

textView.text = "用户:${user.name},年龄:${user.age}"
Log.d("User", "load user id = $userId")

4. 空安全 Null Safety

基础用法

Kotlin 默认变量不能为 null

val name: String = "Tom"
// name = null // 编译报错

var nickName: String? = null

String? 表示这个变量可能为 null

常用操作符

val length1 = nickName?.length       // 安全调用,结果可能为 null
val length2 = nickName?.length ?: 0  // Elvis 操作符,给默认值
val length3 = nickName!!.length      // 强制非空,null 时崩溃

伪代码

读取可能为空的对象:
    如果对象不是 null:
        调用它的方法或属性
    否则:
        返回 null 或默认值

Android 常见用法

val title = intent.getStringExtra("title") ?: "默认标题"
supportActionBar?.title = title

IntentBundle、网络返回、数据库读取的数据都可能为空,Kotlin 空安全能把很多 NPE 提前变成编译期提醒。


5. 函数 Function

基础用法

fun add(a: Int, b: Int): Int {
    return a + b
}

fun printUser(name: String) {
    println("user = $name")
}

单表达式函数可以简写:

fun add(a: Int, b: Int) = a + b

默认参数和具名参数

fun showToast(message: String, duration: Int = Toast.LENGTH_SHORT) {
    Toast.makeText(context, message, duration).show()
}

showToast(message = "保存成功")
showToast(message = "加载中", duration = Toast.LENGTH_LONG)

Java 对比

Java 常用方法重载解决默认参数:

void showToast(String message) {
    showToast(message, Toast.LENGTH_SHORT);
}

void showToast(String message, int duration) {
    ...
}

Kotlin 用默认参数后,可以少写很多重载。


6. if 是表达式

基础用法

Kotlin 的 if 可以返回值。

val score = 88
val result = if (score >= 60) {
    "及格"
} else {
    "不及格"
}

伪代码

如果条件成立:
    result = A
否则:
    result = B

Android 常见用法

val visible = if (items.isEmpty()) View.GONE else View.VISIBLE
emptyView.visibility = visible

7. when

基础用法

when 类似 Java 的 switch,但更强大,也可以返回值。

fun level(score: Int): String {
    return when (score) {
        in 90..100 -> "优秀"
        in 60..89 -> "及格"
        else -> "继续努力"
    }
}

Android 常见用法

when (view.id) {
    R.id.saveButton -> save()
    R.id.cancelButton -> finish()
}

处理 UI 状态:

when (state) {
    is UiState.Loading -> showLoading()
    is UiState.Content -> showContent(state.data)
    is UiState.Error -> showError(state.message)
}

8. 类和构造函数

基础用法

class User(val id: Long, var name: String) {
    fun printInfo() {
        println("$id - $name")
    }
}

使用:

val user = User(1L, "Tom")
user.name = "Jerry"
user.printInfo()

Java 对比

class User {
    private final long id;
    private String name;

    User(long id, String name) {
        this.id = id;
        this.name = name;
    }
}

Kotlin 把构造函数、字段、getter/setter 合在一起写,代码更短。

Android 常见用法

class UserRepository(private val api: UserApi) {
    fun getUser(id: Long): User {
        return api.getUser(id)
    }
}

9. data class

基础用法

data class 适合表示数据对象,编译器会自动生成 equals()hashCode()toString()copy() 等。

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

fun main() {
    val user = User(1, "Tom", 18)
    val newUser = user.copy(age = 19)

    println(user)
    println(newUser)
}

Android 常见用法

data class UserUiState(
    val loading: Boolean = false,
    val users: List<User> = emptyList(),
    val errorMessage: String? = null
)

UI 状态、接口返回、数据库实体都很适合用 data class


10. object 单例

基础用法

Kotlin 用 object 声明单例。

object AppLogger {
    fun log(message: String) {
        println(message)
    }
}

fun main() {
    AppLogger.log("hello")
}

Java 对比

class AppLogger {
    private static final AppLogger INSTANCE = new AppLogger();

    static AppLogger getInstance() {
        return INSTANCE;
    }
}

Android 常见用法

object UserSession {
    var token: String? = null

    fun isLogin(): Boolean {
        return token != null
    }
}

注意:单例会跟随进程存在,不适合随便持有 Activity,否则可能造成内存泄漏。


11. companion object

基础用法

companion object 类似 Java 里的静态成员。

class DetailActivity : AppCompatActivity() {
    companion object {
        const val EXTRA_USER_ID = "extra_user_id"

        fun createIntent(context: Context, userId: Long): Intent {
            return Intent(context, DetailActivity::class.java)
                .putExtra(EXTRA_USER_ID, userId)
        }
    }
}

使用:

val intent = DetailActivity.createIntent(this, userId = 1001L)
startActivity(intent)

Android 常见用法

  • 定义 Intent extra key。
  • 定义 Fragment.newInstance()
  • 放置常量、工厂方法。

12. 集合 List / Set / Map

基础用法

Kotlin 区分只读集合和可变集合。

val names: List<String> = listOf("Tom", "Jerry")
val mutableNames: MutableList<String> = mutableListOf("Tom")

mutableNames.add("Jerry")

Map:

val userMap = mapOf(
    1L to "Tom",
    2L to "Jerry"
)

val mutableMap = mutableMapOf<Long, String>()
mutableMap[1L] = "Tom"

伪代码

只读集合:
    外部不能通过这个引用修改集合
可变集合:
    可以 add/remove/put

Android 常见用法

class UserAdapter : RecyclerView.Adapter<UserViewHolder>() {
    private val users = mutableListOf<User>()

    fun submitList(newUsers: List<User>) {
        users.clear()
        users.addAll(newUsers)
        notifyDataSetChanged()
    }
}

13. Lambda

基础用法

Lambda 是一段可以作为值传递的代码。

val printer: (String) -> Unit = { message ->
    println(message)
}

printer("hello")

集合操作:

val users = listOf("Tom", "Jerry", "Alice")
val result = users.filter { name ->
    name.length > 3
}

只有一个参数时可以用 it

val result = users.filter { it.length > 3 }

Android 常见用法

button.setOnClickListener {
    saveUser()
}

Java 匿名内部类:

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        saveUser();
    }
});

Kotlin 简化后更适合写 UI 回调。


14. 扩展函数 Extension Function

基础用法

扩展函数可以给已有类“增加”函数,实际是静态方法语法糖。

fun String.isPhoneNumber(): Boolean {
    return this.length == 11 && this.all { it.isDigit() }
}

fun main() {
    println("13800138000".isPhoneNumber())
}

Android 常见用法

fun View.visible() {
    visibility = View.VISIBLE
}

fun View.gone() {
    visibility = View.GONE
}

loadingView.visible()
contentView.gone()

理解重点

扩展函数没有真的修改原类,也不能访问原类的 private 成员。它让工具方法写起来更贴近调用对象。


15. 作用域函数

Kotlin 常见作用域函数有 letrunwithapplyalso

let:常用于非空处理和结果转换

val title: String? = intent.getStringExtra("title")

title?.let {
    textView.text = it
}

apply:常用于配置对象

val intent = Intent(this, DetailActivity::class.java).apply {
    putExtra("id", 1001L)
    putExtra("name", "Tom")
}

also:常用于顺手做一件事,并返回原对象

val user = User(1L, "Tom").also {
    Log.d("User", "create $it")
}

记忆表

函数作用域对象返回值常见用途
letitLambda 结果非空后执行、转换
runthisLambda 结果计算一段结果
withthisLambda 结果对已有对象批量操作
applythis原对象初始化配置
alsoit原对象打日志、附加动作

16. 智能类型转换

基础用法

Kotlin 使用 is 判断类型后,编译器会自动转换类型。

fun printLength(value: Any) {
    if (value is String) {
        println(value.length)
    }
}

Android 常见用法

when (item) {
    is TextItem -> showText(item.text)
    is ImageItem -> showImage(item.url)
}

在 Java 中通常需要手动强转:

if (value instanceof String) {
    String text = (String) value;
    System.out.println(text.length());
}

17. 密封类 sealed class

基础用法

sealed class 适合表达有限种状态。配合 when 使用时,编译器能检查是否处理完整。

sealed class UiState {
    object Loading : UiState()
    data class Content(val users: List<User>) : UiState()
    data class Error(val message: String) : UiState()
}

fun render(state: UiState) {
    when (state) {
        UiState.Loading -> showLoading()
        is UiState.Content -> showUsers(state.users)
        is UiState.Error -> showError(state.message)
    }
}

Android 常见用法

  • 页面状态:Loading、Content、Empty、Error。
  • 网络结果:Success、Failure、Loading。
  • 列表 item 类型:Title、Content、Banner。

18. 接口和实现

基础用法

interface UserRepository {
    fun getUser(id: Long): User
}

class DefaultUserRepository(
    private val api: UserApi
) : UserRepository {
    override fun getUser(id: Long): User {
        return api.getUser(id)
    }
}

Java 转 Kotlin 重点

  • Kotlin 继承类和实现接口都用 :
  • 重写方法必须写 override
  • 类默认不能被继承,需要 open
open class BasePresenter

class UserPresenter : BasePresenter()

Android 常见用法

Repository、UseCase、Navigator、Analytics 等都适合用接口隔离实现。


19. 泛型

基础用法

class Box<T>(val value: T)

fun main() {
    val intBox = Box(1)
    val stringBox = Box("hello")
}

泛型函数:

fun <T> firstOrNull(items: List<T>): T? {
    return if (items.isEmpty()) null else items[0]
}

Android 常见用法

abstract class BaseAdapter<T> : RecyclerView.Adapter<BaseViewHolder>() {
    protected val items = mutableListOf<T>()

    fun submitList(newItems: List<T>) {
        items.clear()
        items.addAll(newItems)
        notifyDataSetChanged()
    }
}

泛型能让通用组件复用,同时保留类型安全。


20. 委托属性 by

基础用法

Kotlin 的 by 可以把某些行为委托给另一个对象。

val lazyValue: String by lazy {
    println("init")
    "Hello"
}

第一次访问时才初始化。

Android 常见用法

class MainActivity : AppCompatActivity() {
    private val viewModel: MainViewModel by viewModels()
}

by viewModels() 是 Jetpack 提供的属性委托,帮你从 ViewModelProvider 获取 ViewModel。


21. 解构声明

基础用法

data class 支持解构。

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

fun main() {
    val user = User(1L, "Tom")
    val (id, name) = user

    println(id)
    println(name)
}

Android 常见用法

val map = mapOf("id" to "1001", "name" to "Tom")

for ((key, value) in map) {
    Log.d("Map", "$key = $value")
}

22. 异常处理

基础用法

Kotlin 没有受检异常,try 也可以作为表达式。

val number = try {
    "123".toInt()
} catch (e: NumberFormatException) {
    0
}

Android 常见用法

val result = runCatching {
    api.loadUsers()
}.getOrElse {
    emptyList()
}

网络请求、文件读取、JSON 解析都应该处理失败情况。


23. 协程 Coroutine 入门

基础概念

协程用于写异步代码。它不是线程,但可以挂起和恢复,让异步代码看起来像同步代码。

基础用法

suspend fun loadUser(id: Long): User {
    return api.getUser(id)
}

在 ViewModel 中调用:

class UserViewModel(
    private val repository: UserRepository
) : ViewModel() {

    fun loadUser(id: Long) {
        viewModelScope.launch {
            val user = repository.getUser(id)
            showUser(user)
        }
    }
}

伪代码

启动协程:
    在后台等待网络结果
    等结果回来后继续执行下一行
    如果生命周期结束,取消任务

Android 常见用法

  • viewModelScope.launch {}:ViewModel 生命周期内执行任务。
  • lifecycleScope.launch {}:Activity / Fragment 生命周期内执行任务。
  • withContext(Dispatchers.IO) {}:切到 IO 线程做文件、数据库、网络操作。

24. Flow 入门

基础概念

Flow 是 Kotlin 协程里的异步数据流。它适合表示会持续变化的数据,比如数据库查询结果、搜索输入、页面状态。

val nameFlow: Flow<String> = flow {
    emit("Tom")
    emit("Jerry")
}

收集数据:

lifecycleScope.launch {
    nameFlow.collect { name ->
        textView.text = name
    }
}

Android 常见用法

class UserViewModel : ViewModel() {
    private val _uiState = MutableStateFlow(UiState.Loading)
    val uiState: StateFlow<UiState> = _uiState

    fun load() {
        viewModelScope.launch {
            _uiState.value = UiState.Content(repository.getUsers())
        }
    }
}

Fragment 中:

viewLifecycleOwner.lifecycleScope.launch {
    viewModel.uiState.collect { state ->
        render(state)
    }
}

25. Android 中的 Kotlin 最小实战

目标

写一个非常小的页面逻辑:点击按钮后加载用户,显示 Loading、成功或失败。

数据模型

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

页面状态

sealed class UserUiState {
    object Loading : UserUiState()
    data class Content(val user: User) : UserUiState()
    data class Error(val message: String) : UserUiState()
}

Repository

class UserRepository {
    suspend fun getUser(id: Long): User {
        delay(500)
        return User(id = id, name = "Kotlin User")
    }
}

ViewModel

class UserViewModel : ViewModel() {
    private val repository = UserRepository()

    private val _uiState = MutableStateFlow<UserUiState>(UserUiState.Loading)
    val uiState: StateFlow<UserUiState> = _uiState

    fun loadUser(id: Long) {
        viewModelScope.launch {
            _uiState.value = UserUiState.Loading
            _uiState.value = runCatching {
                repository.getUser(id)
            }.fold(
                onSuccess = { UserUiState.Content(it) },
                onFailure = { UserUiState.Error(it.message ?: "未知错误") }
            )
        }
    }
}

Activity / Fragment 伪代码

class UserFragment : Fragment() {
    private val viewModel: UserViewModel by viewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        loadButton.setOnClickListener {
            viewModel.loadUser(id = 1001L)
        }

        viewLifecycleOwner.lifecycleScope.launch {
            viewModel.uiState.collect { state ->
                when (state) {
                    UserUiState.Loading -> showLoading()
                    is UserUiState.Content -> showUser(state.user)
                    is UserUiState.Error -> showError(state.message)
                }
            }
        }
    }
}

这段代码串起来用了哪些基础语法

语法出现位置作用
data classUser快速定义数据对象
sealed classUserUiState表达有限页面状态
suspendgetUser()声明挂起函数
viewModelScope.launchloadUser()启动协程
StateFlowuiState暴露 UI 状态
LambdasetOnClickListenercollect写回调
whenrender state分发不同状态
空安全it.message ?: "未知错误"避免空指针

Java 转 Kotlin 常见坑

1. Kotlin 类默认不能继承

open class BaseRepository
class UserRepository : BaseRepository()

2. Kotlin 变量默认非空

var name: String? = null

不要一上来就写 !!,优先用 ?.?:

3. == 比较内容,=== 比较引用

val a = "Tom"
val b = "Tom"

println(a == b)   // true
println(a === b)  // 是否同一个对象引用

4. 集合只读不等于绝对不可变

val list: List<String> = mutableListOf("A")

List 引用不能调用 add(),但底层对象可能仍然是可变集合。

5. 不要在 Activity 单例里持有 Context

object BadHolder {
    var activity: Activity? = null
}

这样可能导致内存泄漏。需要 Context 时,优先考虑 applicationContext 或短生命周期传参。


推荐学习顺序

  1. 先跑通 valvar、函数、字符串模板。
  2. 学会空安全:??.?:
  3. 学会类、data classobjectcompanion object
  4. 学会集合和 Lambda,因为 Android 回调和列表数据天天用。
  5. 学会 whensealed class,用来写页面状态。
  6. 最后再学协程和 Flow,把网络、数据库、UI 状态串起来。

小抄

Java 写法Kotlin 写法
final String name = "Tom";val name = "Tom"
String name = null;var name: String? = null
if (obj != null) obj.run();obj?.run()
condition ? a : bif (condition) a else b
switchwhen
POJOdata class
static field / methodcompanion object
Singletonobject
anonymous listenerLambda
utility methodextension function
async callbackcoroutine / Flow

结束语

Kotlin 的重点不是“语法更短”,而是把空安全、函数式写法、状态表达、异步任务这些 Android 高频问题变得更清楚。刚开始不要追求一次掌握所有高级语法,能把页面状态、点击回调、列表数据、网络加载写顺,就已经能在 Android 项目里快速上手。