基本语法
概述
本章详细介绍Kotlin的基本语法规则,包括标识符、关键字、注释、包声明、导入语句等基础概念。掌握这些语法规则是编写正确Kotlin代码的基础。
标识符和命名规则
标识符规则
kotlin
// 有效的标识符
val name = "Kotlin"
val userName = "john_doe"
val _privateVar = 42
val `special name` = "backticks allow spaces"
// 无效的标识符(编译错误)
// val 123name = "error" // 不能以数字开头
// val class = "error" // 不能使用关键字
// val user-name = "error" // 不能包含连字符命名约定
kotlin
// 类名:PascalCase
class UserManager
class DatabaseConnection
// 函数和变量:camelCase
fun calculateTotal() {}
val firstName = "John"
var currentUser = null
// 常量:UPPER_SNAKE_CASE
const val MAX_RETRY_COUNT = 3
const val API_BASE_URL = "https://api.example.com"
// 包名:小写,用点分隔
package com.example.myapp.utils
// 文件名:PascalCase或camelCase
// UserManager.kt
// databaseUtils.kt关键字
硬关键字(不能用作标识符)
kotlin
// 声明关键字
class MyClass
fun myFunction()
val myValue = 10
var myVariable = 20
// 控制流关键字
if (true) { }
else { }
when (x) { }
for (i in 1..10) { }
while (true) { }
do { } while (false)
// 其他关键字
import kotlin.collections.*
package com.example
return 42
throw Exception()
try { } catch (e: Exception) { }软关键字(在特定上下文中有特殊含义)
kotlin
// 在特定位置有特殊含义
class Person {
constructor(name: String) // constructor是软关键字
init { // init是软关键字
println("Initializing")
}
companion object { // companion和object是软关键字
const val DEFAULT_NAME = "Unknown"
}
}注释
单行注释
kotlin
// 这是单行注释
val name = "Kotlin" // 行尾注释
// TODO: 实现用户验证功能
// FIXME: 修复空指针异常
// NOTE: 这个方法需要优化多行注释
kotlin
/*
* 这是多行注释
* 可以跨越多行
* 用于详细说明
*/
val version = "1.9"
/*
* 嵌套注释也是支持的
* /* 这是嵌套的注释 */
* 外层注释继续
*/文档注释 (KDoc)
kotlin
/**
* 计算两个数的和
*
* @param a 第一个数
* @param b 第二个数
* @return 两数之和
* @throws IllegalArgumentException 当参数无效时
* @since 1.0
* @author Kotlin Developer
*/
fun add(a: Int, b: Int): Int {
require(a >= 0 && b >= 0) { "参数必须为非负数" }
return a + b
}
/**
* 用户数据类
*
* @property id 用户唯一标识符
* @property name 用户姓名
* @property email 用户邮箱地址
* @constructor 创建一个新的用户实例
*/
data class User(
val id: Long,
val name: String,
val email: String
)包声明和导入
包声明
kotlin
// 文件开头声明包名
package com.example.myapp.models
// 包名通常反映目录结构
// src/main/kotlin/com/example/myapp/models/User.kt导入语句
kotlin
// 导入特定类
import java.util.Date
import kotlin.math.PI
// 导入包中的所有内容
import kotlin.collections.*
// 导入并重命名(别名)
import java.util.Date as JavaDate
import kotlin.collections.List as KotlinList
// 导入顶级函数
import kotlin.math.sqrt
import kotlin.math.pow
fun main() {
val date = JavaDate()
val list: KotlinList<String> = listOf("a", "b", "c")
val result = sqrt(16.0)
}默认导入
kotlin
// 这些包会自动导入,无需显式导入
// kotlin.*
// kotlin.annotation.*
// kotlin.collections.*
// kotlin.comparisons.*
// kotlin.io.*
// kotlin.ranges.*
// kotlin.sequences.*
// kotlin.text.*
// JVM平台还会自动导入:
// java.lang.*
// kotlin.jvm.*语句和表达式
语句 vs 表达式
kotlin
fun main() {
// 语句:执行操作但不返回值
println("Hello") // 语句
var x = 10 // 语句
// 表达式:计算并返回值
val sum = 5 + 3 // 5 + 3 是表达式
val max = if (x > 5) x else 5 // if是表达式
// when也是表达式
val grade = when (85) {
in 90..100 -> "A"
in 80..89 -> "B"
else -> "C"
}
}块表达式
kotlin
fun main() {
// 块的最后一个表达式是块的值
val result = {
val a = 10
val b = 20
a + b // 这是块的返回值
}()
println("Result: $result") // 输出: Result: 30
// 函数体也是块表达式
fun calculate(): Int {
val x = 5
val y = 10
x * y // 返回值,等同于 return x * y
}
}分号
kotlin
// Kotlin中分号是可选的
val name = "Kotlin"
val version = 1.9
// 同一行多个语句需要分号分隔
val a = 1; val b = 2; val c = 3
// 通常不推荐在同一行写多个语句
// 更好的写法:
val a = 1
val b = 2
val c = 3字面量
数字字面量
kotlin
fun main() {
// 整数字面量
val decimal = 123
val long = 123L
val hexadecimal = 0x7B
val binary = 0b1111011
// 浮点数字面量
val double = 123.45
val float = 123.45f
val scientific = 1.23e2 // 123.0
// 下划线分隔符(提高可读性)
val million = 1_000_000
val creditCard = 1234_5678_9012_3456L
val bytes = 0xFF_EC_DE_5E
println("Decimal: $decimal")
println("Million: $million")
}字符字面量
kotlin
fun main() {
// 字符字面量
val char = 'A'
val digit = '9'
val space = ' '
// 转义字符
val tab = '\t'
val newline = '\n'
val backslash = '\\'
val quote = '\''
val doubleQuote = '\"'
// Unicode字符
val unicode = '\u0041' // 'A'
val emoji = '\u1F600' // 😀
println("Char: $char")
println("Unicode: $unicode")
}字符串字面量
kotlin
fun main() {
// 普通字符串
val simple = "Hello, Kotlin!"
// 转义字符串
val escaped = "Line 1\nLine 2\tTabbed"
// 原始字符串(三重引号)
val raw = """
|This is a raw string
|It can contain newlines
|And "quotes" without escaping
|Backslashes \ are literal
""".trimMargin()
// 字符串模板
val name = "Kotlin"
val version = 1.9
val template = "Welcome to $name version $version!"
val expression = "Length of name: ${name.length}"
println(template)
println(expression)
println(raw)
}布尔字面量
kotlin
fun main() {
val isTrue = true
val isFalse = false
// 布尔运算
val and = true && false // false
val or = true || false // true
val not = !true // false
println("Boolean values: $isTrue, $isFalse")
}操作符优先级
kotlin
fun main() {
// 算术操作符优先级(从高到低)
val result1 = 2 + 3 * 4 // 14 (不是 20)
val result2 = (2 + 3) * 4 // 20
// 比较操作符
val comparison = 5 > 3 && 2 < 4 // true
// 赋值操作符优先级最低
var x = 0
x += 2 * 3 // x = x + (2 * 3) = 6
println("Results: $result1, $result2, $comparison, $x")
}类型系统基础
基本类型
kotlin
fun main() {
// 数字类型
val byte: Byte = 127
val short: Short = 32767
val int: Int = 2147483647
val long: Long = 9223372036854775807L
val float: Float = 3.14f
val double: Double = 3.14159265359
// 字符类型
val char: Char = 'K'
// 布尔类型
val boolean: Boolean = true
// 字符串类型
val string: String = "Kotlin"
// 类型检查
println("int is Int: ${int is Int}")
println("string is String: ${string is String}")
}可空类型
kotlin
fun main() {
// 非空类型
var name: String = "Kotlin"
// name = null // 编译错误
// 可空类型
var nullableName: String? = "Kotlin"
nullableName = null // 允许
// 类型检查和转换
if (nullableName != null) {
println("Length: ${nullableName.length}") // 智能转换
}
// 安全转换
val obj: Any = "Hello"
val str: String? = obj as? String // 安全转换
println("Safe cast result: $str")
}作用域和可见性
局部作用域
kotlin
fun main() {
val outerVar = "outer"
if (true) {
val innerVar = "inner"
println("Access outer: $outerVar") // 可以访问外部变量
println("Access inner: $innerVar")
}
// println(innerVar) // 编译错误:无法访问内部变量
// 块作用域
run {
val blockVar = "block"
println("Block variable: $blockVar")
}
// println(blockVar) // 编译错误
}函数作用域
kotlin
// 顶级函数
fun topLevelFunction() {
println("Top level function")
}
class MyClass {
// 成员函数
fun memberFunction() {
println("Member function")
}
// 局部函数
fun outerFunction() {
fun localFunction() {
println("Local function")
}
localFunction() // 调用局部函数
}
}编码约定
缩进和格式
kotlin
// 使用4个空格缩进
class Person(
val name: String,
val age: Int,
val email: String
) {
fun introduce() {
println("Hello, I'm $name")
}
}
// 链式调用
val result = listOf(1, 2, 3, 4, 5)
.filter { it > 2 }
.map { it * 2 }
.sum()命名约定总结
kotlin
// 包名:全小写,用点分隔
package com.example.myapp
// 类和接口:PascalCase
class UserService
interface DatabaseRepository
// 函数和属性:camelCase
fun calculateTotal() {}
val userName = "john"
// 常量:UPPER_SNAKE_CASE
const val MAX_SIZE = 100
// 枚举常量:UPPER_SNAKE_CASE
enum class Color {
RED, GREEN, BLUE
}常见语法错误
1. 分号使用错误
kotlin
// 错误:不必要的分号
fun main() {
val name = "Kotlin"; // 不需要分号
println(name); // 不需要分号
}
// 正确
fun main() {
val name = "Kotlin"
println(name)
}2. 可空性错误
kotlin
// 错误:忘记处理可空性
fun processName(name: String?) {
// println(name.length) // 编译错误
}
// 正确:处理可空性
fun processName(name: String?) {
println(name?.length ?: 0)
}3. 类型推断错误
kotlin
// 错误:模糊的类型推断
// val list = emptyList() // 编译错误
// 正确:明确指定类型
val list = emptyList<String>()
// 或者
val list: List<String> = emptyList()最佳实践
- 遵循Kotlin编码约定
- 使用有意义的变量和函数名
- 适当使用注释,特别是KDoc
- 保持代码简洁和可读
- 充分利用类型推断,但在必要时明确指定类型
下一步
掌握了基本语法后,让我们学习Kotlin的程序结构,包括类、对象、包等组织代码的方式。
下一章: 程序结构
练习题
- 编写一个程序,展示所有基本数据类型的使用
- 创建一个包含完整KDoc注释的函数
- 实践不同类型的字符串字面量和模板
- 编写代码展示操作符优先级的影响
- 创建一个程序来演示作用域规则