在上一课中,我们搭建了 Kotlin 学习环境并完成了第一个程序。本节课将深入 Kotlin 基础语法的核心 ------ 变量、数据类型与运算符。这些是任何编程语言的基石,掌握它们将让你能够编写有实际功能的代码,为后续学习函数、类等概念打下基础。
一、变量与常量:程序中的 "数据容器"
变量和常量是存储数据的基本单元,Kotlin 对 "可变性" 有严格区分,这也是它与其他语言(如 Python)的重要区别之一。
1. var(可变变量)与 val(不可变常量)
Kotlin 中通过 var
和 val
声明变量,核心区别在于是否可重新赋值:
- var(variable 的缩写) :声明可变变量,可以在初始化后重新赋值;
- val(value 的缩写) :声明不可变常量 ,初始化后不能重新赋值(类似 Java 中的
final
)。
kotlin
// 可变变量:可以重新赋值
var age = 20
age = 21 // 合法,var 允许修改
// 不可变常量:初始化后不能修改
val name = "Kotlin"
// name = "Java" // 编译错误!val 不允许重新赋值
最佳实践 :优先使用 val
,仅在确实需要修改时使用 var
。这能减少代码中的 "意外修改",让程序更稳定、更易维护(尤其在多线程场景)。
2. 变量声明的两种方式:显式类型 vs 类型推导
Kotlin 是静态类型语言,但支持 "类型推导",无需每次都显式指定变量类型:
- 显式类型指定 :格式为
var/val 变量名: 类型 = 值
,明确告诉编译器变量的类型; - 类型推导 :格式为
var/val 变量名 = 值
,编译器会根据赋值自动推断变量类型。
kotlin
// 显式指定类型
var score: Int = 95
val pi: Double = 3.14159
// 类型推导(推荐)
var height = 175 // 编译器自动推断为 Int 类型
val isStudent = true // 自动推断为 Boolean 类型
注意:类型推导仅在声明时赋值有效。如果声明时不赋值(延迟初始化),必须显式指定类型:
kotlin
var address: String // 延迟初始化,必须显式指定类型
address = "北京市朝阳区" // 后续赋值
3. 变量作用域:变量的 "有效范围"
变量的作用域指它能被访问的代码范围,Kotlin 中主要分为局部变量 和全局变量:
(1)局部变量
定义在函数、代码块(如 if
、for
内部)中的变量,仅在所在代码块内有效:
kotlin
fun printMessage() {
// 函数内的局部变量,仅在 printMessage() 中可访问
val message = "Hello, Local Variable"
println(message)
}
fun main() {
printMessage()
// println(message) // 编译错误!message 是 printMessage() 的局部变量
}
(2)全局变量
定义在类、文件顶层(不属于任何函数或类)的变量,在整个文件或类中可访问:
kotlin
// 文件顶层的全局变量,整个文件都能访问
val globalVersion = "1.0.0"
fun checkVersion() {
println("当前版本:$globalVersion") // 可直接访问全局变量
}
fun main() {
checkVersion() // 输出:当前版本:1.0.0
}
注意:全局变量会一直占用内存,应避免过度使用。优先使用局部变量,遵循 "最小作用域原则"。
二、基本数据类型:Kotlin 的 "数据积木"
Kotlin 提供了丰富的基本数据类型,用于存储不同类型的数据。与 Java 不同,Kotlin 的基本数据类型不是 "原始类型"(如 int) ,而是 "对象类型",但仍保持高效的性能(编译时会优化为原始类型)。
1. 数值类型:存储数字的 "工具箱"
Kotlin 提供 6 种数值类型,按精度和范围从小到大排列:
Byte | 8 位 | -128 ~ 127 | 存储小整数(节省空间) |
---|---|---|---|
Short | 16 位 | -32768 ~ 32767 | 中等范围整数 |
Int | 32 位 | -2^31 ~ 2^31-1(约 -21 亿~21 亿) | 普通整数(默认首选) |
Long | 64 位 | -2^63 ~ 2^63-1(约 -900 亿亿~900 亿亿) | 大整数 |
Float | 32 位 | 单精度浮点数(约 ±3.4e38,7 位有效数字) | 精度要求不高的小数 |
Double | 64 位 | 双精度浮点数(约 ±1.8e308,15 位有效数字) | 高精度小数(默认首选) |
使用注意:
- 声明
Long
类型时,数值后需加L
后缀:val bigNum: Long = 10000000000L
; - 声明
Float
类型时,数值后需加F
后缀:val pi: Float = 3.14F
; - 整数默认是
Int
类型,小数默认是Double
类型。
kotlin
val b: Byte = 127
val s: Short = 32000
val i = 1000 // 默认为 Int
val l = 10000000000L // Long 类型必须加 L
val f = 3.14F // Float 类型必须加 F
val d = 3.14159 // 默认为 Double
2. 字符类型 Char:单个字符的 "容器"
Char
用于存储单个字符,用单引号 '
包裹,与 Java 有两点关键区别:
- Kotlin 的
Char
不能直接当作数字使用(Java 中可以); - 支持 Unicode 字符(包括中文、表情符号等)。
kotlin
val c1: Char = 'A' // 英文字符
val c2: Char = '中' // 中文字符(支持 Unicode)
val c3: Char = '\u0041' // Unicode 编码表示(对应 'A')
// 特殊语法规则:Char 在左侧时可以与数字相加
val y1 = 'A' + 1 // 合法,结果为 'B'('A' 的 ASCII 码是 65,加 1 后为 66,对应 'B')
// 数字在左侧时不能与 Char 相加
// val y2 = 1 + 'A' // 编译错误!Kotlin 不允许数字在左侧与 Char 直接相加
如需将 Char
转换为对应的 ASCII 码,可显式调用 toInt()
方法,这样无论顺序如何都能正确计算:
kotlin
val charCode = 'A'.toInt() // 转换为 ASCII 码 65
val sum = 1 + charCode // 合法,结果为 66
println(sum.toChar()) // 输出:'B'
3. 布尔类型 Boolean:逻辑判断的 "开关"
Boolean
用于表示逻辑值,只有两个可能的值:true
(真)和 false
(假),主要用于条件判断(如 if
语句)。
kotlin
val isReady = true
val hasError = false
// 逻辑判断示例
if (isReady) {
println("准备就绪")
} else {
println("尚未准备")
}
三、字符串类型详解:文本处理的 "利器"
字符串(String
)用于存储文本,是编程中最常用的数据类型之一。Kotlin 对字符串的支持非常灵活,提供了多种便捷操作。
1. 字符串创建:单行与多行
Kotlin 支持两种字符串创建方式:
- 单行字符串 :用双引号
""
包裹,内容在一行内; - 多行字符串 :用三重引号
"""
包裹,可直接换行,保留格式(无需转义符\n
)。
kotlin
// 单行字符串
val singleLine = "这是一个单行字符串"
// 多行字符串(保留换行和缩进)
val multiLine = """
这是第一行
这是第二行
这是第三行
""".trimIndent() // trimIndent() 用于去除每行前的多余缩进
println(multiLine)
// 输出:
// 这是第一行
// 这是第二行
// 这是第三行
注意 :多行字符串默认会保留每行开头的缩进,trimIndent()
方法可自动去除这些多余缩进,让输出更整洁。
2. 字符串拼接:连接文本的两种方式
拼接字符串有两种常用方法:
+
号拼接 :直接用+
连接字符串和其他数据类型;- 字符串模板 :用
$
符号引用变量或表达式,更简洁高效。
kotlin
val name = "Kotlin"
val version = 1.9
// + 号拼接(较繁琐)
val info1 = "编程语言:" + name + ",版本:" + version
println(info1) // 输出:编程语言:Kotlin,版本:1.9
// 字符串模板(推荐)
val info2 = "编程语言:$name,版本:$version"
println(info2) // 输出:同上
// 模板中使用表达式(需用 ${} 包裹)
val a = 10
val b = 20
val sumStr = "两数之和:${a + b}" // 表达式 a + b 的结果会被插入
println(sumStr) // 输出:两数之和:30
优势 :字符串模板比 +
号拼接更高效(避免创建过多临时字符串),且代码更易读。
3. 常用字符串方法:处理文本的 "工具箱"
Kotlin 的 String
类提供了丰富的方法,以下是最常用的几个:
方法名 | 功能描述 | 示例 |
---|---|---|
length |
获取字符串长度(字符数) | "hello".length → 5 |
substring(start, end) |
截取子串(从 start 到 end-1) | "Kotlin".substring(1, 4) → "otl" |
equals(other) |
判断两个字符串内容是否相等 | "a".equals("A") → false |
compareTo(other) |
比较字符串(按字典顺序) | "apple".compareTo("banana") → 负数 |
startsWith(prefix) |
判断是否以指定前缀开头 | "Kotlin".startsWith("Ko") → true |
endsWith(suffix) |
判断是否以指定后缀结尾 | "Kotlin".endsWith("lin") → true |
trim() |
去除首尾空格 | " hello ".trim() → "hello" |
split(delimiter) |
按分隔符拆分字符串为列表 | "a,b,c".split(",") → ["a", "b", "c"] |
kotlin
val str = " Kotlin Programming "
println(str.length) // 输出:20(包含前后空格)
println(str.trim()) // 输出:"Kotlin Programming"(去除空格)
println(str.startsWith("Ko")) // 输出:false(原字符串前有空格)
println(str.trim().startsWith("Ko")) // 输出:true(去除空格后)
println(str.substring(2, 8)) // 输出:"Kotlin"(截取索引 2 到 7 的字符)
四、运算符与表达式:数据运算的 "规则"
运算符用于对数据进行运算,结合变量和常量可组成表达式(有返回值的代码片段)。Kotlin 的运算符大部分与 Java 类似,但有一些细节差异。
1. 算术运算符:处理数字计算
运算符 | 功能 | 示例 |
---|---|---|
+ |
加法 | 5 + 3 → 8 |
- |
减法 | 5 - 3 → 2 |
* |
乘法 | 5 * 3 → 15 |
/ |
除法 | 5 / 2 → 2 (整数除法) |
% |
取余(模) | 5 % 2 → 1 |
++ |
自增 | var a=1; a++ → 2 |
-- |
自减 | var b=3; b-- → 2 |
注意:
- 整数除法(
/
)会自动舍弃小数部分(如5 / 2 = 2
,而非 2.5); - 自增 / 自减运算符(
++
/--
)放在变量前后的区别:a++
:先使用a
的值,再自增;++a
:先自增,再使用a
的值。
kotlin
val num1 = 10
val num2 = 3
println(num1 + num2) // 13
println(num1 - num2) // 7
println(num1 * num2) // 30
println(num1 / num2) // 3(整数除法,舍弃小数)
println(num1.toDouble() / num2) // 3.333...(转换为 Double 后除法)
println(num1 % num2) // 1(10 除以 3 余 1)
var count = 5
println(count++) // 输出 5(先使用后自增)
println(count) // 输出 6
var score = 80
println(++score) // 输出 81(先自增后使用)
println(score) // 输出 81
2. 赋值运算符:给变量赋值
基本赋值运算符是 =
,此外还有复合赋值运算符(结合算术运算和赋值):
运算符 | 等价表达式 | 示例 |
---|---|---|
= |
直接赋值 | a = 5 |
+= |
a = a + b |
a += 3 → a = a + 3 |
-= |
a = a - b |
a -= 2 → a = a - 2 |
*= |
a = a * b |
a *= 4 → a = a * 4 |
/= |
a = a / b |
a /= 2 → a = a / 2 |
%= |
a = a % b |
a %= 3 → a = a % 3 |
kotlin
var x = 10
x += 5 // 等价于 x = x + 5 → x = 15
x *= 2 // 等价于 x = x * 2 → x = 30
x -= 8 // 等价于 x = x - 8 → x = 22
println(x) // 输出:22
3. 比较运算符:判断数据关系
比较运算符用于判断两个数据的关系,返回 Boolean
类型(true
或 false
)。
运算符 | 功能描述 | 示例 |
---|---|---|
== |
比较内容是否相等(结构相等) | "abc" == "abc" → true |
!= |
比较内容是否不相等 | 5 != 3 → true |
> |
大于 | 10 > 5 → true |
< |
小于 | 10 < 5 → false |
>= |
大于等于 | 5 >= 5 → true |
<= |
小于等于 | 3 <= 2 → false |
=== |
比较引用是否相同(引用相等) | (见下方说明) |
关键区别 :==
vs ===
==
:检查 "结构相等"(内容是否相同),相当于 Java 的equals()
方法;===
:检查 "引用相等"(是否指向内存中的同一个对象),相当于 Java 的==
运算符。
kotlin
val str1 = "Hello"
val str2 = "Hello"
val str3 = String("Hello".toCharArray()) // 新建一个内容相同的字符串对象
println(str1 == str2) // true(内容相同)
println(str1 == str3) // true(内容相同)
println(str1 === str2) // true(Kotlin 字符串常量池优化,引用相同)
println(str1 === str3) // false(str3 是新对象,引用不同)
4. 逻辑运算符:组合条件判断
逻辑运算符用于连接多个布尔表达式,进行复杂逻辑判断:
运算符 | 功能描述 | 示例 |
---|---|---|
&& |
逻辑与(短路) | true && false → false |
` | ` | |
! |
逻辑非 | !true → false |
短路特性:
&&
:如果左侧表达式为false
,则右侧表达式不会执行 (因为整体结果已确定为false
);||
:如果左侧表达式为true
,则右侧表达式不会执行 (因为整体结果已确定为true
)。
kotlin
val hasMoney = true
val hasTime = false
// 逻辑与:两个条件都为 true 才返回 true
val canBuy = hasMoney && hasTime
println(canBuy) // false(hasTime 为 false)
// 逻辑或:至少一个条件为 true 就返回 true
val canRelax = hasMoney || hasTime
println(canRelax) // true(hasMoney 为 true)
// 逻辑非:取反
val isPoor = !hasMoney
println(isPoor) // false
// 短路特性示例
var count = 0
val result = false && (count++ > 0) // 左侧为 false,右侧不执行
println(count) // 0(count 未自增)
五、类型转换:不同数据类型的 "桥梁"
Kotlin 不支持 "隐式类型转换"(如 Java 中 int
自动转为 long
),必须显式调用转换方法 。每种基本类型都提供了转换为其他类型的方法(如 toInt()
、toDouble()
等)。
kotlin
val numInt: Int = 100
// val numLong: Long = numInt // 编译错误!Kotlin 不允许隐式转换
val numLong: Long = numInt.toLong() // 正确:显式转换为 Long
val numFloat: Float = numInt.toFloat() // 转换为 Float
val numStr: String = numInt.toString() // 转换为字符串
// 字符串转数字(需确保字符串内容是有效数字)
val str = "123"
val strToInt = str.toInt() // 转换为 Int
val strToDouble = str.toDouble() // 转换为 Double
注意 :字符串转数字时,如果内容不是有效数字(如 "abc"
),会抛出 NumberFormatException
异常,后续课程会讲解如何处理这类异常。
六、实践练习:巩固基础的 "小项目"
为了帮助你巩固本节课内容,我们来编写一个简单的 "个人信息卡片" 程序,综合运用变量、数据类型和运算符:
kotlin
fun main() {
// 1. 定义个人信息变量
val name = "张三"
var age = 25
val height: Double = 1.75
val isStudent = true
// 2. 计算明年的年龄(使用算术运算符)
val nextYearAge = age + 1
// 3. 拼接个人信息字符串(使用字符串模板)
val info = """
个人信息卡片
姓名:$name
今年年龄:$age
明年年龄:$nextYearAge
身高:${height}米
是否学生:${if (isStudent) "是" else "否"} // 模板中使用表达式
""".trimIndent()
// 4. 输出结果
println(info)
}
尝试修改变量值或添加更多信息(如体重、爱好),观察输出变化,加深对知识点的理解。