资讯动态

Kotlin基本语法详解:变量、函数、空安全与集合操作

发布时间:2026/10/6 9:22:15 来源:尧图企业网站定制
做Android开发这几年我越来越觉得Kotlin不学不行。如果你正打算入行Android开发或者已经在用Java写业务却还没碰过Kotlin这篇“Kotlin基本语法”系列的第一篇就是给你准备的。先说清楚这篇不讲大而全的理论只讲你从零开始写Android项目时最常用到的那些词法、语法和用法比如变量、函数、控制流、空安全和集合操作。我尽量用实际Android开发场景来讲而不是把官方文档翻译一遍。Kotlin入门的第一个认知是它没有你想的那么难。那些看着很科幻的符号比如?.、!!、?:本质上就是帮你少写一堆if判断和空指针处理的语法糖。这篇会用通俗的类比、完整的代码示例和我在真实项目里踩过的坑把Kotlin最核心的基本语法讲透。1. 学习Kotlin之前先搞清楚这3个基本问题1.1 为什么Android开发现在绕不开Kotlin2017年Google正式宣布Kotlin成为Android官方支持的开发语言2019年又在开发者大会上把Kotlin列为首选语言。这意味着什么意味着你新写的Android项目如果还用纯Java虽然不至于被淘汰但很多官方文档、第三方库、开源项目的示例代码都已经默认用Kotlin写了。你不会Kotlin连查资料都会比别人多一道翻译的工序。Kotlin是JetBrains推出的基于JVM的语言和Java跑在同一个运行时环境。它最大的价值不是“取代Java”而是让开发者在写Android的时候少受Java那些老毛病的折磨。最典型的就是空安全设计。做过Android的都知道空指针异常NPE简直是崩溃日志里的常客很多线上崩溃都是因为一个对象忘判空。Kotlin在类型系统层面区分了“可空类型”和“不可空类型”你试图把一个可空值赋给不可空变量时编译器直接报错把问题提前到编码阶段。另外Kotlin的lambda表达式、扩展函数和协程让Android开发里的异步回调、工具类封装、线程切换写起来都舒服很多。你后面如果接触到Jetpack Compose、协程、Flow这些新东西Kotlin语法就是它们的地基。所以早点把语法基础补上后面学新框架会轻松很多。1.2 Kotlin与Java的关系不是替代而是无缝协作很多人有个误解觉得学了Kotlin就得把Java代码全部Rewrite。实际上Kotlin和Java可以100%互操作两个语言的文件可以同时存在于一个项目里互相调用没有任何障碍。Kotlin编译后生成的是JVM字节码运行在Android的ART虚拟机或标准JVM上底层是同一套东西。这意味着你可以循序渐进。老项目里Java的Activity可以直接调Kotlin写的工具类Kotlin的类也可以继承Java的基类、实现Java接口。Android Studio还提供“Convert Java File to Kotlin File”的代码转换功能一键把单个Java文件转成Kotlin。我工作室里的老项目就是从几个工具类开始慢慢转的完全不用停服务器做重构。不过互操作也有一些要注意的坑比如Java代码里的字段在Kotlin眼里可能是“平台类型”编译器不强制判断它是否可空真出了问题还是得靠你自己注意。这个我在后面专门写一节先把基础语法过完再说。1.3 谁适合这篇教程零基础要准备什么这篇适合两种人一种是有Java基础、想快速切到Kotlin的Android开发另一种是刚接触编程、第一门语言就打算学Kotlin的纯新手。有Java基础的人看这篇会发现很多概念是似曾相识的比如类、接口、继承、集合所以上手会很快。纯新手也不需要慌Kotlin本身在设计上就比Java简洁很多语法更接近人的自然语言反而更容易理解。在动手之前请确保你准备好这些一台能跑的电脑操作系统不限Windows、macOS、Linux都行。安装好Android Studio版本建议用最新的稳定版里面内置了Kotlin支持不用额外装插件。JDK环境Android Studio新版一般自带JBRJetBrains Runtime不需要单独折腾JDK配置。一个看得懂报错的眼睛以及遇到问题先自查的习惯。Kotlin的报错提示其实很友好大部分情况英文翻译过来就能明白。环境这块不用追求最新稳定就好。我刚开始学的时候用的还是Android Studio 3.x现在新版本基本都是Android Studio Hedgehog之后界面变化了不少但Kotlin相关的操作反而更顺滑了。2. 先搭好开发环境把第一个Kotlin程序跑起来2.1 Android Studio和Kotlin插件的版本选择现在的Android Studio对Kotlin的支持已经做得非常完善从你新建项目选择语言那一栏开始选Kotlin就直接给你搭好全部环境。如果你装的是比较老的版本才需要手动安装Kotlin插件。在新版Android Studio里你只需要确认两件事一是你的Gradle插件版本AGP和Kotlin插件版本是配套的二是项目里的build.gradle.kts或build.gradle里声明了kotlin-android插件。我见过不少新手在这个阶段卡住报错信息千奇百怪比如“Unresolved reference: kotlin”或者“Kotlin not configured”。大多数原因就是项目没启用Kotlin插件。解决办法也很简单打开项目根目录的build.gradle.kts确认里面有kotlin(android)这个插件声明并且在模块的build.gradle.kts里也apply了。新版默认就有了不用自己写。如果还是搞不定试着File菜单里的“Sync Project with Gradle Files”强制同步一下八成能解决。2.2 新建一个Kotlin工程理解入口函数我建议你先别急着写界面先新建一个最简单的项目感受一下Kotlin代码长什么样。打开Android Studio选择“New Project”选“Empty Views Activity”语言选择“Kotlin”。项目建好后重点看MainActivity.kt这个文件你会看到这样一个入口class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } }这个就是一个最基础的Kotlin类。它继承自AppCompatActivity和Java的extends AppCompatActivity是同一个意思只不过Kotlin用冒号代替了extends。你注意看onCreate方法前面的override关键字这个是Kotlin里表示方法重写的标记和Java的Override注解功能一致但写起来更直接。不过我更建议你额外做一个练习在项目里新建一个普通的Kotlin文件不要继承任何东西直接写一个main函数来运行纯Kotlin代码。因为Android项目很多时候不起模拟器也可以测试简单语法逻辑你可以写一个fun main()然后在里面打印变量、调用函数再运行它快速看输出。这是学习语法的最高效路径——不依赖Android环境专注看Kotlin本身的运行结果。fun main() { val name 秋裤 println(Hello, $name) }2.3 几个IDE使用技巧自动转换、快速修复和类型提示新人最容易忽略的就是IDE本身的学习成本。Android Studio的Kotlin支持是一等公民用好这些功能学习效率能翻倍。第一个技巧是Java转Kotlin。你把一段Java代码直接复制到一个.kt文件里Android Studio会提示你是否要转换格式。或者选中代码后通过菜单栏的“Code Convert Java File to Kotlin File”来显式转换。这个方法特别适合我这种从Java转过来的人因为我可以通过对比转换前后的代码直观地理解Kotlin的语法差异。第二个技巧是AltEnter快速修复。Kotlin编译器报错时光标停在红色代码上按AltEnter会弹出修复建议很多情况它会直接告诉你少写了什么符号、需要加什么转换甚至能自动生成你要实现的成员。比如你写了一个类实现某个接口挨个补方法时这个快捷键能救命。第三个技巧是显式类型提示。Kotlin用类型推断省略了很多变量类型的书写但如果你是新手可能还是希望看到类型。Android Studio可以在编辑器的“View Appearance”里开启“Show parameter name hints”或者在代码里临时把鼠标悬停到变量上查看推断出的类型。看久了自然就能自己推断出类型了下一步再关掉这些提示也不迟。3. Kotlin最核心的基本语法变量、函数、控制流3.1 变量声明val和var到底怎么选Java里声明变量是String name 张三;类型写在变量前面。Kotlin反过来先写变量名再写类型中间用冒号隔开并且多用val和var来声明。val name: String 张三 var age: Int 25val是只读变量赋值后不能再修改相当于Java里的final。var是可重新赋值的变量相当于普通Java变量。我在实际开发里的习惯是默认都用val只有当这个变量确实需要被重新赋值时才用var。为什么这么做因为val让代码的可读性和安全性更好——别人拿到这个变量知道它不会被偷偷改掉逻辑推理起来不需要担心它中途变化。Kotlin有强大的类型推断。你写val count 10编译器自动知道它是Int类型写val price 19.9默认推断为Double。大多数时候你不需要显式写类型但有些场景为了代码清晰或者为了声明一个抽象类型的变量还是需要写明。还要注意Kotlin的基本数据类型和Java不完全一样。Kotlin的Int、Long、Float、Double、Boolean、Char都是对象类型但编译时会根据上下文尽可能优化成基本类型。你不需要在代码里区分int和Integer、boolean和BooleanKotlin帮你自动处理了装箱和拆箱。我的建议是学Kotlin的时候别再用Java那套思路去纠结类型直接声明并使用它比你想的更智能。3.2 字符串模板和函数定义Kotlin的字符串模板是我用过最舒服的特性。Java拼字符串要么用硬拼要么用String.format写起来又长又繁琐。Kotlin直接在字符串里用$变量名嵌入内容还可以用${表达式}包住复杂表达式。val user 张三 val loginMessage 用户 $user 登录成功 val priceInfo 总价${calculateTotal()}第二行的${calculateTotal()}直接调用了函数字符串里执行方法也没问题。这个特性在Android里非常实用比如拼接日志、提示文案、网络请求参数写法都清爽不少。不过要注意如果你要拼的是对象属性的值比如用户 ${user.name}花括号不能省。再来看函数的定义。Java里定义一个方法public int add(int a, int b) { return a b; }。Kotlin简洁得多fun add(a: Int, b: Int): Int { return a b }前面不需要写public因为Kotlin默认可见性就是public。返回类型写在参数括号的后面用冒号连接。如果函数体只有一个表达式可以直接用等号简化这叫表达式函数体fun add(a: Int, b: Int) a bKotlin还支持默认参数和命名参数。比如fun showToast(msg: String, duration: Int Toast.LENGTH_SHORT) { ... } showToast(加载失败) showToast(加载失败, Toast.LENGTH_LONG) showToast(duration Toast.LENGTH_LONG, msg 加载失败)举个例子你可能立刻就能感受到好处你封装一个网络请求函数有10个参数调用时如果只传其中3个用命名参数写起来清晰且不容易错位。这套语法在Android开发里经常用来给自定义View写属性方法。3.3 when和for、while控制流写法Kotlin里的when表达式完全可以替代Java的switch。我见过很多人到Kotlin里还在写if-else if-else一大串其实用when更清晰。它的基本结构是这样的when (code) { 200 - println(成功) 404 - println(页面不存在) 500, 503 - println(服务器错误) else - println(未知状态) }注意一点when是一个表达式它可以直接返回结果这也是它比switch强大的地方。写法上每个分支的右边不用写breakKotlin自动处理。你还用when判断条件而不只是值比如when (x) { in 1..10 - ... }这个用in关键字配合区间来判断范围写起来比Java的区间判断舒服很多。循环方面Kotlin最常用的for循环和Java差异很大它是基于区间和集合的遍历。比如遍历1到10不需要写i0; i10; i这种三段式for (i in 1..10) { println(i) } for (i in 1 until 10) { // 不包含10 println(i) } for (i in 10 downTo 1 step 2) { // 从10递减到1每次减2 println(i) }1..10表示闭区间1到10until表示不含终点的区间downTo是倒序step是步长。我第一次用的时候觉得这个设计真的舒服因为日常写遍历时最烦的就是纠结边界、写错上下标。Kotlin把这些语义直接用符号表达清楚了。while循环和Java基本一致该用就用不需要特殊记忆。真正需要的是判断怎么选择能预知循环次数用for不确定次数用while。3.4 空安全的魔鬼细节?、?:、!!、?.怎么用Kotlin的空安全是它最受瞩目的特性也是新人最容易懵的地方。先说一个核心概念在Kotlin里普通类型的变量不允许赋值为null只有声明为可空类型在类型后面加?才能赋null。val name: String? null val age: Int 30 // 不能赋null否则编译报错当你拿到一个可空变量想访问它的属性或方法不能直接name.length。你必须在前面加上安全调用符?.意思是“如果name不为null才执行否则整个表达式结果为null”。val length name?.length // 如果name是nulllength也是null这里length的类型变成了Int?。如果你想要一个非空的默认值用Elvis操作符?:val displayLength name?.length ?: 0这个?:的含义是左侧表达式不为null就用左侧的值否则用右侧的值。名字叫Elvis操作符因为?:倒过来看像一张留着飞机头的脸。我第一次见到这个符号还以为是闲鱼上抢商品时用的“抢”字其实作用特别单纯给一个可能的null值兜底。还有!!操作符表示“我确信这个值不为null”如果实际上为null会直接抛空指针异常。这个我在生产代码里是强烈反对乱用的因为它的本质就是绕过了安全机制。只有在绝对确定的情况下才用比如某个值在Android生命周期里已经确保初始化。大多数时候能用?.和?:解决的就不要用!!。最后一个高频搭配是letname?.let { println(名字长度 ${it.length}) }如果name不为null就执行let里的代码块it就是name。这个写法在Android里经常用来安全地处理非空数据。比如网络请求回来后要更新UI先判空再操作用?.let很舒服。4. 类、对象和集合Kotlin里的高频进阶语法4.1 data class实体类怎么写才优雅如果你用Java写过实体类肯定记得那一堆样板代码每个字段的getter、settertoString()equals()和hashCode()。用IDE生成一遍能省时间但每次改一个字段就要重新生成很烦。Kotlin用data class直接解决data class User( val id: Int, val name: String, val email: String? )就这么几行编译器自动生成equals()、hashCode()、toString()、copy()方法也会根据val和var生成相应的访问器。在Android开发里data class最适合用来做网络接口的响应模型、数据库实体、RecyclerView的Item模型。data class还有一个我很喜欢的功能解构声明。你可以把一个对象拆成多个变量val user User(1, 张三, zhangsanexample.com) val (id, name, email) user println(id$id, name$name)注意解构声明对属性的顺序有要求它按声明顺序依次赋值。实际开发中这个语法在遍历列表、从函数返回多个值时特别有用。不过有一点提醒copy()方法是浅拷贝如果类里有引用类型的字段修改拷贝对象的嵌套属性原对象也会受影响。做数据更新时要注意。4.2 object单例、伴生对象和顶层常量Kotlin里没有静态方法和静态字段的概念它是用object和companion object来模拟Java静态语法的场景。先说object它定义了一个单例对象整个程序运行期间只有一个实例。object AppConfig { val ENV prod const val API_BASE_URL https://api.example.com }使用方式很直接AppConfig.ENV、AppConfig.API_BASE_URL。这个相当于Java的工具类或全局常量类Android里我经常用它保存全局配置、缓存策略、通用方法。和Java的静态类比它更安全——只有一个实例不需要担心多实例导致状态不一致。再来说companion object。它出现在普通类的内部模拟Java里的静态成员class UserManager { companion object { val instance UserManager() fun createDefault(): UserManager UserManager() } }调用时直接UserManager.instance或UserManager.createDefault()。这个在Android开发里经常用来给Fragment、Activity写newInstance()之类的工厂方法或者保存一个全局单例对象。顶层常量也很常用。你可以直接在.kt文件的顶层声明一个常量或函数不属于任何类整个模块都能访问。比如写一个Constants.kt文件const val PAGE_SIZE 20 const val MAX_FILE_SIZE 1024 * 1024 * 5 fun formatTime(timestamp: Long): String { ... }注意const val只能修饰基本类型和String而且必须在顶层或object里声明。如果你想声明一个自定义对象的常量用val加by lazy或直接初始化。4.3 集合操作List、MutableList和lambda三板斧Kotlin的集合类型分两种只读的和可变的。listOf()创建只读列表不能增删改mutableListOf()创建可变列表。val names listOf(张三, 李四, 王五) val mutableNames mutableListOf(张三) mutableNames.add(李四)注意“只读”并不等于“绝对不可变”——如果这个列表底层实际上是可变列表通过其他引用仍然可以修改。真正的不可变列表需要额外的不可变实现。但日常开发中把只读集合当成不可变来用已经能避免很多意外的修改问题。集合操作中最有生产力的是lambda表达式配合标准库函数。比如过滤、映射、遍历val users listOf( User(1, 张三, null), User(2, 李四, liexample.com) ) val emails users.map { it.email } // 提取所有email val namedUsers users.filter { it.name ! } // 过滤掉空名字 val sortedUsers users.sortedBy { it.id } // 按id排序 users.forEach { println(it.name) }我刚刚还在疑惑val emails users.map { it.email }里的email是用户id不是字符串类型其实这个表达不对User的email是String?应该写成users.map { it.name }或users.map { it.email ?: 未知 }。在本文的示例语境里重点是展示map、filter、sortedBy的用法读者使用时要根据实际情况处理可空类型。反正你只要记得集合处理是Kotlin里非常高频的技能Android开发中从网络接口拿到List后做展示前的过滤、排序、去重都是靠这些函数。此外Kotlin还提供了大量好用的标准库函数比如mapIndexed可以同时拿到下标和元素flatMap可以将嵌套集合拍平groupBy可以根据某个字段分组。一开始不需要全部记住先掌握map、filter、forEach、sortedBy这几个遇到具体的业务需求再去查文档也来得及。5. 把Kotlin语法塞进Android项目3个实战场景5.1 用lambda替换setOnClickListenerKotlin的lambda表达式让Android的接口回调写起来特别简洁。你回忆一下Java里给一个按钮设置点击监听button.setOnClickListener(new View.OnClickListener() { Override public void onClick(View v) { Log.d(TAG, button clicked); } });Kotlin可以写成这样button.setOnClickListener { Log.d(TAG, button clicked) }这背后是Kotlin的“函数字面量与接收者”特性因为setOnClickListener接收的接口只有一个待实现方法Kotlin允许直接用lambda表达式作为它的实现。如果lambda只有一个参数默认用it代替不需要写v -。实际开发里这种简洁带来最大的好处是逻辑更紧凑。比如你可以直接把点击后的逻辑写进一个小函数再把它放进去button.setOnClickListener(::handleClick) fun handleClick(view: View) { // 处理点击逻辑 }函数引用的写法有一个前提handleClick的签名必须和OnClickListener.onClick(View)一致。这个方法在几个按钮共用一个点击逻辑时特别实用。5.2 lateinit和可空类型处理findViewById/数据填充在Java里你写TextView tv findViewById(R.id.tv);然后直接在onCreate里使用。但Kotlin对变量初始化的要求更严格如果你声明一个非空类型属性必须在构造或init块里初始化否则编译器报错。这在Android里很别扭因为很多View是在onCreate里才赋值的。解决方案有两个。第一个是lateinit var用来延迟初始化class MainActivity : AppCompatActivity() { private lateinit var tvTitle: TextView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) tvTitle findViewById(R.id.tv_title) tvTitle.text 标题 } }注意lateinit只能在var上用不能用val因为val必须在构造时初始化而lateinit的整个机制就是延迟赋值。如果你在赋值之前访问它会报“lateinit property has not been initialized”异常。这个异常我排查过好多次大多数原因是某个回调在onCreate之前被调用或者Fragment里视图还没创建好就去访问了。第二个方案是by lazy它适合属性只在第一次访问时才初始化的场景private val tvTitle: TextView by lazy { findViewById(R.id.tv_title) }使用by lazy时有几个细节默认情况下lazy是线程安全的它在第一次访问时计算值之后缓存结果。lambda里的代码只有在第一次访问时执行。这叫按需初始化如果你一个页面里有很多View但只有用到时候才绑定可以省一部分初始化开销。但要注意在Fragment里用by lazy时如果旋转屏幕导致View重建lazy缓存的值还是旧的可能拿到废弃的View。还有一种场景是处理数据填充网络请求返回的对象可能为null展示到UI时需要兜底。比如val email user.email ?: 未填写 tvEmail.text email这种安全调用配合Elvis操作符的模式在Android UI代码里出现的频率极高。记住一个原则所有来自外部、网络、SP、数据库的值都要视为可空然后用?.和?:安全处理。5.3 用data class和when写RecyclerView的多类型ItemRecyclerView在Android日常开发中使用频率极高而Kotlin的data class和when表达式结合起来能让Adapter的代码清晰很多。比如你有一个聊天页面消息类型有文本、图片、系统提示三类sealed class ChatItem { data class Text(val content: String) : ChatItem() data class Image(val url: String) : ChatItem() data class System(val message: String) : ChatItem() }在RecyclerView.Adapter里你根据item类型来决定创建哪种ViewHolderoverride fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return when (viewType) { TYPE_TEXT - TextViewHolder(...) TYPE_IMAGE - ImageViewHolder(...) else - SystemViewHolder(...) } }sealed class密封类也是Kotlin的一个重要特性它限制子类只能在同一个文件里定义配合when表达式可以做到穷尽分支检查——如果某个子类没有在when里覆盖编译器会直接报错。这个特性在做多类型列表时非常方便因为你少了一次“忘记处理某种类型”的出错机会。当然这一节的核心还是语法应用只要你能体会出data class负责数据结构、when负责分支判断、密封类保证分支穷尽就已经把Kotlin最有价值的基础语法用上了。后面系列文章我再展开讲RecyclerView与Kotlin的完整配合。6. 新手最容易踩的6个坑以及我的排查建议6.1 “类型不匹配”和“未初始化”报错Kotlin的编译报错通常很明确最常见的几类可以快速定位。第一个是“Type mismatch”比如你写val email: String user.email但user.email是String?编译器就会报错。解决办法是判空或者取默认值val email: String user.email ?: 。第二个是“Variable xxx must be initialized”这个提示通常发生在两种场景一是声明了非空类型属性但没初始化二是lateinit属性没赋值就被访问。遇到时要检查代码执行顺序确认赋值逻辑在访问逻辑之前。第三个是“Smart cast to String is impossible”智能类型转换失败。Kotlin有个智能转换特性当一个可空变量判空后编译器会在后续代码中自动把它当成非空类型。比如val name: String? getName() if (name ! null) { println(name.length) // 这里可以直接用因为编译器知道name非空 }但如果中间涉及到成员变量可变的var属性智能转换就可能失效因为编译器不确定它会不会在并发时被其他线程修改。解决办法是用局部变量先把值保存下来或者用?.let处理。6.2 “Unresolved reference”的常见来源“Unresolved reference”是我见过新手遇到最高频的编译错误之一。它通常意味着编译器找不到某个类、某个包或某个导入。原因大致有几种项目还没同步Gradle依赖你写错了包名或类名有些Android SDK类漏了import。我的排查顺序是这样的先看是不是拼写问题再看import是否完整然后File Sync Project with Gradle Files最后Build Clean Project。如果还不行把Android Studio的缓存清掉File Invalidate Caches / Restart。90%的“Unresolved reference”都能在第三步解决。别一上来就卸载重装太耗时了。6.3 Java互操作中的平台类型陷阱当Java代码出现在Kotlin代码中Kotlin编译器不知道Java的某个方法返回的值是否可以为null所以它把这种类型叫“平台类型”用String!这种方式暗示。平台类型意味着你既可以把它当作非空也可以当作可空编译器都不拦着。真正的风险是如果你拿它当作非空用了但底层Java代码运行时会返回null就会在运行时触发空指针。比如Java的某个方法// Java代码 public static String getToken() { return null; // 实际可能为null }Kotlin这边val token: String JavaClass.getToken() // 编译不报错但运行时可能NPE这种问题的排查成本比较高因为错误不在编译期。我的建议是对所有Java接口返回的引用一律当成可空来对待尤其是那些你自己没看过源码的方法。新代码里尽量多用Kotlin少和Java的旧接口做太多无保护交互。6.4 使用!!的后果和代替方案!!是一个危险的双刃剑。我在实际Code Review时只要看到!!第一反应就是这里可能藏着一个线上崩溃。因为它表达的意思是“我强行认为它不是null”一旦你判断失误就是一个标准的空指针异常。代替方案其实都很成熟。如果是函数参数可以在入口处做一次校验用requireNotNull()或checkNotNull()它们会抛出带提示信息的异常。如果是可空集合用filterNotNull()过滤掉null。如果是可空对象的一个字段用?.加上?:兜底。只有当你完全确定某个值不可能为null比如是当前类自己赋值的lateinit属性且已初始化才考虑用!!。我记得有一次线上报错后台数据源突然返回了一个带null字段的对象而代码里写的是data.name!!.length直接崩溃。后来把!!改成data.name?.length ?: 0稳定运行了很久。这个教训分享给所有新人能不用!!就不用它不是酷炫技巧是埋雷。6.5 扩展函数使用时的导入问题Kotlin的扩展函数很有用比如你可以给Context加一个showToast方法fun Context.showToast(msg: String) { Toast.makeText(this, msg, Toast.LENGTH_SHORT).show() }然后在Activity里调用showToast(保存成功)但新手经常会遇到“Unresolved reference”或者无法调用的尴尬。原因是扩展函数在哪个包声明就必须在哪个包导入。如果你的扩展函数写在com.example.utils包里调用文件就需要import com.example.utils.showToast。这和Java的静态导入逻辑相似忘了import就会找不到。我的习惯是把通用扩展函数集中放在几个文件里并在文件顶部做import避免到处找函数。6.6 版本与Gradle相关的基础排查Kotlin版本、Gradle插件版本不匹配也会出现奇怪的问题。例如“Kotlin could not find the required JDK tools”这种报错一般是你本机的JDK环境有问题检查JAVA_HOME和项目用的JDK版本。Gradle同步失败往往有错误日志第一行就说明了缺什么依赖、连不上什么仓库。我建议从一开始就把Gradle和Kotlin版本用默认模板的版本不要自己手动升级。尤其是新手官方模板的版本组合一定经过测试轻易改版本是自我折磨。做的项目变多之后再慢慢了解Gradle的版本管理逻辑也不晚。7. Kotlin基本语法一总结与下一步学习路线这篇虽然定位是“基本语法一”但内容覆盖了Kotlin日常最常用的语法块val/var变量声明、函数与默认参数、when/for控制流、空安全三兄弟、data class和object单例、集合和lambda、密封类与多类型Adapter。这些已经不是纯粹的“语法知识”了而是直接能套进Android项目里用的基础能力。我个人带新人时的经验是基础语法的学习不要追求一次性吸收一定要配合练习。你可以试着用Kotlin重写一个自己以前用Java写过的小模块比如一个列表页面一个登录页或者一个简单的网络请求工具类。在改写过程中遇到的编译报错才是真正帮你记忆语法的手段。不要怕报错报错是你最好的老师。我当初也是从一行行代码查错查过来的写了几个页面之后Kotlin的语法基本就顺手了。下一篇文章我大概率会接着讲Kotlin里的面向对象进阶比如密封类怎么和接口配合、泛型在代码里的实战用法、数据类和协变逆变这些稍微深一点的内容。到时候我会尽量多结合网络请求和UI展示的真实场景来写而不是为了讲语法而讲语法。如果你想第一时间看到后续内容建议先把这篇里的代码都动手跑一遍尤其是空安全、集合操作和data class那块把基础打牢后面的内容才能接得住。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑