第 1 篇|Kotlin 基础入门 —— 变量、函数与空安全

第 1 篇|Kotlin 基础入门 ------ 变量、函数与空安全

哈喽,各位零基础想入门 Android 开发的小伙伴们~ 今天咱们正式开启 Kotlin 学习之旅的第一篇,聚焦 Android 开发的核心基础:变量、函数,并且重点攻克让无数新手头疼又绕不开的「空安全」机制。

很多新手刚接触 Android 开发,都会纠结同一个问题:先学 Java 还是 Kotlin?这里直接给结论------学 Android,首选 Kotlin,也只能是 Kotlin。无论从 Google 官方的战略导向,还是实际开发效率来看,Kotlin 早已是 Android 开发的绝对主流。学会它,你才能跟上当下的开发节奏。接下来,咱们一步步拆解,从最基础的语法到核心重难点,全程附上可运行的代码示例,保证新手也能零门槛上手。

一、为什么学 Android 首选 Kotlin?

在 Android 开发领域,Kotlin 早已不是"选修课",而是"必修课"。核心原因可以归结为两点:官方全力支持 + 语言本身降维打击级别的优势,双buff加持,让 Kotlin 成为 Android 新手的最优选择。

1. Google 官方的"亲儿子"待遇

自 2017 年 Google I/O 大会宣布 Kotlin 成为 Android 官方一级开发语言后,Google 便坚定推行「Kotlin-first」战略,全方位资源都在向 Kotlin 倾斜,具体体现在三个方面:

  • 开发工具优先:Android Studio 的新建项目模板默认语言就是 Kotlin,Java 模板反而需要手动切换,可见官方对 Kotlin 的优先级倾斜;

  • 新框架 Kotlin 独占:Android 最新的声明式 UI 框架 Jetpack Compose 仅提供 Kotlin DSL 支持,未来趋势不言而喻,不学 Kotlin 就无法掌握最新开发技术;

  • 官方文档与课程:官方开发者网站上的代码示例、Codelab 实战教程,绝大多数都优先展示 Kotlin 版本,Java 仅作为历史技术栈补充。

简单说:现在出去面试 Android 岗,招聘 JD 里几乎清一色要求"熟练掌握 Kotlin"。不学 Kotlin,相当于输在了起跑线上。

2. Kotlin 对比 Java 的核心优势(新手直观对比)

Kotlin 基于 JVM(Java 虚拟机),能与 Java 代码 100% 互通,但它完美解决了 Java 的诸多历史遗留痛点,对新手更友好、写起来也更高效,两者核心对比如下:

对比维度 Java Kotlin
代码简洁度 极度啰嗦,写一个简单的数据类需要手写构造、getter/setter 等几十行代码 一行搞定,data class User(val name: String)
空指针安全 编译期不设防,运行时空指针(NPE)是头号崩溃元凶 类型系统天生区分可空与非空,编译期就能拦截 90% 的 NPE
函数式编程 支持有限,且在低版本 Android 上受限 天生支持高阶函数、Lambda 表达式,集合操作极其流畅
异步处理 回调地狱,代码难以阅读和维护 内置协程,用同步的写法写出异步的逻辑,代码清晰优雅

结论:对新手而言,Kotlin 的上手难度并不比 Java 高,甚至因为语法糖丰富,写起来更轻松。更重要的是,学会 Kotlin 能帮你从根源上减少 App 崩溃,开发效率直接翻倍,是 Android 入门的最优解。

二、第一个 Kotlin 程序:从 Hello World 开始

实践出真知,学习任何编程语言,都要从"Hello World"开始。咱们用 Android Studio(后简称 AS)来编写第一个 Kotlin 程序,全程实操,新手跟着做就能成功。

1. 准备工作

打开 AS,点击 New Project → Empty Views Activity,在 Language 选项里确保选的是 Kotlin(通常默认就是),其他选项保持默认,点击 Finish,AS 会自动生成好项目结构,无需手动配置。

2. 编写第一个 main 函数

Kotlin 程序的入口是 main 函数,语法比 Java 更简洁。我们在项目里新建一个 Kotlin File(右键包名 → New → Kotlin Class/File,选择 File),命名为 FirstProgram,输入以下代码(含详细注释,新手可直接复制):

kotlin 复制代码
// 单行注释:这是 Kotlin 程序的入口函数
fun main() {
    /*
       多行注释:
       println 输出内容后会自动换行
       print 输出内容后不会自动换行
    */
    println("Hello Kotlin! 我是 Android 新手~")
    print("这是不换行的输出,")
    print("这一句会和上一句连在一起。\n") // \n 是换行转义符
    println("程序运行结束!")
}

3. 运行验证与补充知识点

点击代码行号左侧的绿色三角箭头,选择 Run。等待编译完成后,在 AS 底部的 Run 面板中,你会看到如下输出:

plain 复制代码
Hello Kotlin! 我是 Android 新手~
这是不换行的输出,这一句会和上一句连在一起。
程序运行结束!

恭喜!你的第一个 Kotlin 程序成功运行🎉。这里补充两个新手必知的小知识点,帮你夯实基础:

  • main 函数的另一种形式:支持接收命令行参数,写法为 fun main(args: Array<String>),新手暂时用不到,了解即可;

  • 注释规范:// 是单行注释,/* ... */ 是多行注释,注释不会被编译执行,但好的注释习惯能让你的代码更好懂,新手一定要养成写注释的习惯。

三、变量声明:val 和 var 的核心区别(新手必分清)

变量是程序中存储数据的容器,Kotlin 声明变量只有两个关键字:val 和 var,核心区别在于「是否可重新赋值」。很多新手在这里容易犯晕,咱们用大白话+代码示例,一次性讲透。

1. 语法格式(新手必记)

Kotlin 很聪明,支持「类型推断」,通常不需要你手动指定变量类型,它会根据你赋的值自动判断。核心语法有两种,优先使用第一种:

kotlin 复制代码
// 格式1:自动类型推断(推荐,简洁高效)
val/var 变量名 = 值

// 格式2:显式指定类型(当变量先声明后赋值时使用)
val/var 变量名: 数据类型 = 值

2. val:只读引用,不可重新赋值

val(value 的缩写)修饰的变量只能赋值一次,类似 Java 里的 final 变量,核心特点是「引用不可变」。

kotlin 复制代码
fun main() {
    val name: String = "张三"
    // name = "李四" // ❌ 报错!Val cannot be reassigned(val 不可重新赋值)
    
    val age = 18      // 类型自动推断为 Int(整数)
    // age = 19       // ❌ 报错!
}

3. var:可变变量,可多次赋值

var(variable 的缩写)修饰的变量可以反复修改,核心特点是「引用可变更」,适合变量值需要动态变化的场景。

kotlin 复制代码
fun main() {
    var count = 0
    count = 1          // ✅ 正确,可重新赋值
    count += 10        // ✅ 正确,现在 count 是 11
    
    var message: String = "Hello"
    message = "Hi"     // ✅ 正确,可修改值
}

⚠️ 新手必踩坑点 ①:val 不是绝对的"不可变"

这是新手最容易产生误解的地方:val 只保证「变量本身指向的引用不变」,但不保证引用指向的对象内部属性不变。

kotlin 复制代码
data class User(var name: String, var age: Int)
fun main() {
    val user = User("张三", 18)
    user.age = 19           // ✅ 完全正确!对象内部的属性 age 是 var,可以修改
    // user = User("李四", 20) // ❌ 报错!变量 user 是 val,不能指向新对象
}

避坑原则:优先使用 val,只有明确需要多次改变变量指向时,才用 var。这样能保证代码的稳定性,减少意外修改。

四、基础数据类型与字符串模板

新手只需掌握 4 种常用基础数据类型,就能满足日常 Android 开发需求;而字符串模板是 Kotlin 的"语法糖",能大幅简化字符串拼接,新手必须掌握。

1. 四种常用基础数据类型

类型 说明 示例
Int 整数类型,用于存储年龄、数量等整数 val age = 20
Double 浮点数(小数),用于存储分数、金额等 val price = 99.99
Boolean 布尔值,只有 true(真)或 false(假),用于判断条件 val isLogin = false
String 字符串,用双引号括起来,用于存储文本 val name = "Android"

重要提醒:Kotlin 中的 String 是不可变的,任何修改字符串的操作(如拼接、转大写)都会返回一个新的字符串对象,不会修改原字符串。

2. 字符串模板:$ 的妙用(新手高频使用)

Java 中用 + 号拼接字符串,既繁琐又容易出错,而 Kotlin 的字符串模板用 $ 符号就能轻松搞定,核心有 3 种用法,全部掌握就能应对日常开发:

kotlin 复制代码
fun main() {
    val name = "小明"
    val score = 95.5
    
    // 1. 直接引用变量($ + 变量名)
    println("学生姓名:$name")
    
    // 2. 引用表达式(复杂逻辑用花括号 {} 包起来)
    println("成绩单:$score 分,等级:${if (score >= 90) "优秀" else "良好"}")
    
    // 3. 打印单纯的 $ 符号,前面加反斜杠 \ 转义
    println("这本书的价格是 \$99")
}

运行结果如下,简洁又直观:

plain 复制代码
学生姓名:小明
成绩单:95.5 分,等级:优秀
这本书的价格是 $99

五、Kotlin 核心重难点:空安全机制(Android 开发必掌握)

空指针异常(NullPointerException,简称 NPE)是 Java 开发中永远的痛,俗称「十亿美元的错误」。而 Kotlin 最伟大的创新,就是在编译期就将绝大部分 NPE 扼杀在摇篮里,这也是 Kotlin 最核心的优势。

Kotlin 空安全的核心理念:默认情况下,所有变量都不能为空。只有明确声明为"可空类型",才能赋值为 null。

1. 可空类型 String? 与不可空类型 String(核心区别)

两者的唯一区别,就是在类型名后面加一个问号 ?,新手一定要分清:

kotlin 复制代码
fun main() {
    // 不可空类型:直接写类型名,绝对不能赋值为 null
    var name: String = "张三"
    // name = null  // ❌ 编译报错!Null can not be a value of a non-null type String
    
    // 可空类型:类型名后面加 ?,允许赋值为 null
    var nickname: String? = "阿三"
    nickname = null    // ✅ 正确!可空类型可以置空
}

关键限制:可空类型的变量,不能直接调用它的方法或属性(如 nullableName.length),否则编译不通过。这是 Kotlin 强制你做空检查的手段,从根源上避免 NPE。

2. 三大空安全操作符(必学必会)

为了优雅地处理可空变量,Kotlin 提供了三个强大的操作符,新手需牢记每种操作符的用法和场景,优先使用前两种。

(1)安全调用符 ?.(最常用,优雅避坑)

语法:可空变量?\.方法/属性

作用:如果对象不为 null,就执行后面的方法/属性;如果为 null,直接返回 null,程序不会崩溃,相当于"有值就执行,没值就算了"。

kotlin 复制代码
fun main() {
    val str: String? = "Kotlin"
    println(str?.length)  // 输出 6(str 不为 null,正常获取长度)
    
    val nullStr: String? = null
    println(nullStr?.length) // 输出 null,程序正常运行,不崩溃
}
(2)Elvis 运算符 ?:(给 null 兜底)

语法:可空变量 ?: 默认值

作用:如果左边的表达式结果不为 null,就返回左边;如果为 null,就返回右边的默认值,常和安全调用符配合使用,是处理 null 的"神器"。

kotlin 复制代码
fun main() {
    val nullableName: String? = null
    // 如果 nullableName 为空,就使用 "未命名" 作为默认值
    val realName = nullableName ?: "未命名"
    println(realName) // 输出:未命名
    
    // 配合 ?. 使用,完美处理链式调用(Android 开发高频场景)
    val user: User? = null
    val userName = user?.name ?: "默认用户"
    println(userName) // 输出:默认用户
}

data class User(val name: String, val age: Int)
(3)非空断言 !!.(慎用,新手劝退符)

语法:可空变量\!\!\.方法/属性

作用:强制告诉编译器:"我确定这玩意儿绝不为空,你别管了!"。后果:如果实际上它是 null,App 会立刻崩溃闪退,抛出 KotlinNullPointerException。

kotlin 复制代码
fun main() {
    val str: String? = null
    // 危险操作!!!
    val length = str!!.length // 💥 运行时崩溃,App 直接闪退
}

⚠️ 新手必踩坑点 ②:滥用 !! 导致闪退 + 不会看日志

很多新手遇到可空变量编译报错,图省事直接一个 !! 怼上去,结果编译通过了,App 一到线上就疯狂崩溃,还不会排查问题。这里给出正确做法和排查技巧:

kotlin 复制代码
// 错误示例(新手常犯)
fun printUserName(user: User?) {
    // 滥用 !!,如果 user 为 null,会崩溃
    println("用户姓名:${user!!.name}")
}

// 正确示例(优先使用 ?. 和 ?:)
fun printUserName(user: User?) {
    // 方式1:简洁处理,适合简单场景
    println("用户姓名:${user?.name ?: "未命名"}")
    
    // 方式2:先做 null 判断,适合复杂逻辑
    if (user != null) {
        println("用户姓名:${user.name}")
    } else {
        println("用户姓名:未命名")
    }
}

// 排查技巧:App 闪退后,打开 AS 底部 Logcat 面板,搜索 FATAL EXCEPTION,
// 堆栈信息会精确告诉你哪一行代码因为 !! 断言失败而崩溃,修改为 ?. 或 ?: 即可。

六、综合小案例:用户信息卡打印器(实战练习)

咱们把今天学的变量、函数、空安全全部串起来,写一个实战小案例,巩固所学知识。案例需求清晰,全程无 !!,健壮性拉满,新手可直接复制运行。

案例需求

  • 编写函数 printUserCard(name: String?, age: Int, isLogin: Boolean?)

  • name 可能为空,空时显示"未命名";

  • isLogin 可能为空,空时默认按"未登录"处理;

  • 完全使用空安全语法,严禁出现 !!;

  • 用多行字符串模板打印规范的用户信息卡。

完整代码实现

kotlin 复制代码
fun main() {
    // 测试用例1:全部有值
    printUserCard("张三", 25, true)
    
    // 测试用例2:name 和 isLogin 为空
    printUserCard(null, 18, null)
    
    // 测试用例3:未登录状态
    printUserCard("李四", 30, false)
}

/**
 * 用户信息卡打印器函数
 * @param name 用户名(可空)
 * @param age 年龄(不可空)
 * @param isLogin 登录状态(可空)
 */
fun printUserCard(name: String?, age: Int, isLogin: Boolean?) {
    // 1. 优雅处理 name 为空的情况 (Elvis 运算符)
    val displayName = name ?: "未命名"
    
    // 2. 优雅处理 isLogin 为空的情况,空时视为未登录
    val loginStatus = if (isLogin ?: false) "已登录" else "未登录"
    
    // 3. 使用多行字符串模板打印信息卡,trimIndent() 自动对齐
    println("""
        ======= 用户信息卡 =======
        姓名:$displayName
        年龄:$age
        状态:$loginStatus
        ==========================
    """.trimIndent())
}

运行结果

plain 复制代码
======= 用户信息卡 =======
姓名:张三
年龄:25
状态:已登录
==========================
======= 用户信息卡 =======
姓名:未命名
年龄:18
状态:未登录
==========================
======= 用户信息卡 =======
姓名:李四
年龄:30
状态:未登录
==========================

案例解析

这个案例覆盖了今天所有核心知识点,新手一定要吃透:

  • 函数声明:带参数、带注释,规范编写函数,提升代码可读性;

  • 空安全处理:用 ?: 给 name 和 isLogin 设置默认值,全程无 !!,避免崩溃;

  • 字符串模板:用多行字符串(""" ... """)和 $ 符号,简洁拼接信息;

  • 逻辑判断:结合 if-else 处理登录状态,兼顾简洁性和可读性。

七、总结与下篇预告

恭喜你坚持学完了 Kotlin 基础入门的第一课!我们来快速回顾一下今天的核心收获,帮你梳理记忆:

  • ✅ 变量声明:优先用 val(只读,引用不可变),非必要不用 var(可变);

  • ✅ 基础类型:掌握 Int、Double、Boolean、String 四种常用类型,了解 String 不可变性;

  • ✅ 字符串模板:用 $ 符号快速拼接变量和表达式,告别繁琐的 + 号;

  • ✅ 空安全灵魂三连:可空类型加 ?、安全调用 ?.、Elvis 兜底 ?:;

  • ✅ 避坑指南:val 内部属性可能变、坚决不滥用 !! 断言,学会用 Logcat 排查崩溃。

这些知识是 Android 开发的地基,也是后续学习集合、循环、高阶函数、协程的必备前提。一定要多敲代码、多试错,把基础打牢------编程没有捷径,实操才是王道。

✨ 如果本文对你有帮助,欢迎点赞、收藏,让更多零基础的小伙伴少走弯路!

下篇我们将深入学习 Kotlin 集合、循环与高阶函数,解锁更强大的代码操作能力,不见不散!

相关推荐
t***5442 小时前
如何验证Clang是否在Dev-C++中正常工作
开发语言·c++
charlie1145141912 小时前
嵌入式C++开发第17篇:C++23特性收尾 —— 属性、链接与零开销抽象的最终证明
开发语言·c++·stm32·学习·c++23
lsx2024062 小时前
PHP MySQL Order By
开发语言
笑春风oO2 小时前
使用国内镜像源加速Qt“更新/安装”的方法【Ubuntu篇】
开发语言·qt
asdzx672 小时前
Python: 从 PPT 提取图片和文本
开发语言·python·powerpoint
枫叶丹42 小时前
【HarmonyOS 6.0】AVCodec Kit 同步模式视频编解码深度解析:从API演进到高性能实战
开发语言·华为·harmonyos·视频编解码
jjjava2.02 小时前
计算机体系与进程管理全解析
java·开发语言
AI人工智能+电脑小能手2 小时前
【大白话说Java面试题】【Java基础篇】第5题:HashMap的底层原理是什么
java·开发语言·数据结构·后端·面试·hash-index·hash
谢谢 啊sir2 小时前
L1-120 智慧文本编辑器 - java
java·开发语言