Kotlin基础语法入门
Kotlin基本语法元素
变量声明
在Kotlin中,变量声明使用 var
关键字表示可变变量,使用 val
关键字表示不可变变量(类似于Java中的 final
变量)。例如:
var mutableVariable: Int = 10
val immutableVariable: String = "Hello, Kotlin!"
这里,mutableVariable
是一个可变的整数变量,immutableVariable
是一个不可变的字符串变量。Kotlin 支持类型推断,所以在很多情况下可以省略类型声明:
var number = 20
val message = "Type inference in action"
数据类型
Kotlin 的数据类型分为基本数据类型和引用数据类型。基本数据类型包括 Byte
、Short
、Int
、Long
、Float
、Double
、Boolean
和 Char
。
例如,整数类型 Int
:
val num1: Int = 100
val num2 = 200 // 类型推断为Int
浮点数类型 Float
和 Double
:
val floatNum: Float = 3.14f
val doubleNum = 2.71828 // 类型推断为Double
布尔类型 Boolean
:
val isTrue: Boolean = true
val isFalse = false
字符类型 Char
:
val charA: Char = 'A'
引用数据类型如 String
、数组、类等。String
在 Kotlin 中使用非常方便,支持字符串模板:
val name = "John"
val greeting = "Hello, $name!"
println(greeting)
运算符
算术运算符
Kotlin 提供了常见的算术运算符,如 +
(加法)、-
(减法)、*
(乘法)、/
(除法)和 %
(取模)。
val a = 10
val b = 3
val sum = a + b
val difference = a - b
val product = a * b
val quotient = a / b
val remainder = a % b
println("Sum: $sum, Difference: $difference, Product: $product, Quotient: $quotient, Remainder: $remainder")
比较运算符
比较运算符用于比较两个值,包括 ==
(等于)、!=
(不等于)、>
(大于)、<
(小于)、>=
(大于等于)和 <=
(小于等于)。
val num1 = 10
val num2 = 15
println(num1 == num2)
println(num1 != num2)
println(num1 > num2)
println(num1 < num2)
println(num1 >= num2)
println(num1 <= num2)
逻辑运算符
逻辑运算符有 &&
(逻辑与)、||
(逻辑或)和 !
(逻辑非)。
val condition1 = true
val condition2 = false
println(condition1 && condition2)
println(condition1 || condition2)
println(!condition1)
流程控制语句
if 语句
if
语句用于条件判断。在 Kotlin 中,if
可以作为表达式,有返回值。
val num = 10
val result = if (num > 5) {
"Greater than 5"
} else {
"Less than or equal to 5"
}
println(result)
也可以使用传统的 if - else if - else
结构:
val score = 85
if (score >= 90) {
println("A")
} else if (score >= 80) {
println("B")
} else if (score >= 70) {
println("C")
} else {
println("D")
}
when 语句
when
语句类似于 Java 中的 switch - case
,但功能更强大。它可以接受各种类型的参数。
val day = 3
val dayName = when (day) {
1 -> "Monday"
2 -> "Tuesday"
3 -> "Wednesday"
4 -> "Thursday"
5 -> "Friday"
6 -> "Saturday"
7 -> "Sunday"
else -> "Invalid day"
}
println(dayName)
when
还可以用于更复杂的条件判断,例如:
val num = 15
when {
num % 2 == 0 -> println("$num is even")
num % 2 != 0 -> println("$num is odd")
}
for 循环
for
循环用于遍历集合或执行固定次数的操作。遍历数组:
val numbers = intArrayOf(1, 2, 3, 4, 5)
for (number in numbers) {
println(number)
}
遍历区间:
for (i in 1..5) {
println(i)
}
这里 1..5
表示从 1 到 5 的闭区间。如果要创建开区间,可以使用 until
,例如 1 until 5
表示从 1 到 4。
while 和 do - while 循环
while
循环在条件为真时执行循环体:
var count = 0
while (count < 5) {
println(count)
count++
}
do - while
循环先执行一次循环体,然后再检查条件:
var num1 = 0
do {
println(num1)
num1++
} while (num1 < 5)
函数
函数定义
在 Kotlin 中,函数使用 fun
关键字定义。函数可以有参数和返回值。
fun add(a: Int, b: Int): Int {
return a + b
}
这里定义了一个名为 add
的函数,接受两个 Int
类型的参数,并返回它们的和。如果函数体只有一行代码,可以使用简洁的写法:
fun multiply(a: Int, b: Int) = a * b
函数参数
函数参数可以有默认值,这样在调用函数时可以省略这些参数。
fun greet(name: String, message: String = "Hello") {
println("$message, $name!")
}
greet("John")
greet("Jane", "Hi")
可变参数
使用 vararg
关键字可以定义接受可变数量参数的函数。
fun sum(vararg numbers: Int): Int {
var total = 0
for (number in numbers) {
total += number
}
return total
}
val result1 = sum(1, 2, 3)
val result2 = sum(10, 20, 30, 40)
类与对象
类定义
在 Kotlin 中,使用 class
关键字定义类。类可以包含属性和方法。
class Person {
var name: String = ""
var age: Int = 0
fun introduce() {
println("My name is $name and I'm $age years old.")
}
}
这里定义了一个 Person
类,有 name
和 age
两个属性,以及 introduce
方法。
对象创建
创建类的对象很简单,直接使用类名加括号:
val person1 = Person()
person1.name = "Alice"
person1.age = 25
person1.introduce()
构造函数
类可以有主构造函数和次构造函数。主构造函数是类头的一部分:
class Rectangle(val width: Int, val height: Int) {
fun area() = width * height
}
val rect = Rectangle(5, 10)
println("Rectangle area: ${rect.area()}")
这里主构造函数接受 width
和 height
两个参数,并将它们声明为属性。
次构造函数使用 constructor
关键字定义:
class Circle {
var radius: Double = 0.0
constructor(radius: Double) {
this.radius = radius
}
constructor() : this(1.0) {
}
fun area() = Math.PI * radius * radius
}
val circle1 = Circle(5.0)
val circle2 = Circle()
println("Circle 1 area: ${circle1.area()}")
println("Circle 2 area: ${circle2.area()}")
继承
类继承
在 Kotlin 中,使用 open
关键字修饰可以被继承的类,子类使用 :
符号继承父类。
open class Animal {
open fun makeSound() {
println("Animal makes a sound")
}
}
class Dog : Animal() {
override fun makeSound() {
println("Dog barks")
}
}
val dog = Dog()
dog.makeSound()
这里 Animal
是一个开放类,Dog
类继承自 Animal
并重写了 makeSound
方法。
访问修饰符
Kotlin 有四种访问修饰符:public
(默认)、private
、protected
和 internal
。
public
:所有地方都可以访问。private
:只能在声明它的类内部访问。protected
:在类内部和子类中可以访问。internal
:在同一个模块内可以访问。
例如:
class MyClass {
private var privateProperty = "Private property"
protected var protectedProperty = "Protected property"
internal var internalProperty = "Internal property"
public var publicProperty = "Public property"
private fun privateMethod() {
println("This is a private method")
}
protected fun protectedMethod() {
println("This is a protected method")
}
internal fun internalMethod() {
println("This is an internal method")
}
public fun publicMethod() {
println("This is a public method")
}
}
接口
接口定义
使用 interface
关键字定义接口,接口可以包含抽象方法和默认实现的方法。
interface Shape {
fun area(): Double
fun perimeter(): Double
fun printInfo() {
println("Area: ${area()}, Perimeter: ${perimeter()}")
}
}
这里 area
和 perimeter
是抽象方法,printInfo
是有默认实现的方法。
接口实现
类通过 :
符号实现接口,并实现接口中的抽象方法。
class Square(val side: Double) : Shape {
override fun area() = side * side
override fun perimeter() = 4 * side
}
val square = Square(5.0)
square.printInfo()
集合
列表(List)
Kotlin 中的列表是有序的元素集合。不可变列表使用 listOf
创建,可变列表使用 mutableListOf
创建。
val immutableList = listOf(1, 2, 3, 4)
val mutableList = mutableListOf(5, 6, 7, 8)
mutableList.add(9)
println(immutableList)
println(mutableList)
集合(Set)
集合是不包含重复元素的集合。不可变集合使用 setOf
创建,可变集合使用 mutableSetOf
创建。
val immutableSet = setOf(1, 2, 2, 3)
val mutableSet = mutableSetOf(4, 5, 5, 6)
mutableSet.add(7)
println(immutableSet)
println(mutableSet)
映射(Map)
映射是键值对的集合。不可变映射使用 mapOf
创建,可变映射使用 mutableMapOf
创建。
val immutableMap = mapOf("one" to 1, "two" to 2)
val mutableMap = mutableMapOf("three" to 3, "four" to 4)
mutableMap.put("five", 5)
println(immutableMap)
println(mutableMap)
异常处理
try - catch - finally 块
Kotlin 使用 try - catch - finally
块来处理异常。
try {
val result = 10 / 0
println(result)
} catch (e: ArithmeticException) {
println("Caught an arithmetic exception: ${e.message}")
} finally {
println("This is the finally block")
}
抛出异常
使用 throw
关键字抛出异常。
fun divide(a: Int, b: Int): Int {
if (b == 0) {
throw ArithmeticException("Cannot divide by zero")
}
return a / b
}
try {
val result = divide(10, 0)
println(result)
} catch (e: ArithmeticException) {
println("Caught exception: ${e.message}")
}
Lambda 表达式与高阶函数
Lambda 表达式
Lambda 表达式是一个匿名函数,它可以作为参数传递给其他函数。
val sum: (Int, Int) -> Int = { a, b -> a + b }
val result = sum(3, 5)
println(result)
这里定义了一个 sum
的 Lambda 表达式,它接受两个 Int
参数并返回它们的和。
高阶函数
高阶函数是接受其他函数作为参数或返回一个函数的函数。
fun operate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
val addLambda: (Int, Int) -> Int = { x, y -> x + y }
val subLambda: (Int, Int) -> Int = { x, y -> x - y }
val addResult = operate(10, 5, addLambda)
val subResult = operate(10, 5, subLambda)
println("Add result: $addResult, Sub result: $subResult")
这里 operate
是一个高阶函数,它接受两个整数和一个操作函数作为参数,并返回操作结果。
通过以上对 Kotlin 基础语法的介绍,你应该对 Kotlin 有了一个初步的了解,可以开始编写简单的 Kotlin 程序了。随着进一步深入学习,你会发现 Kotlin 更多强大的特性和应用场景。例如在 Android 开发中,Kotlin 已经成为官方推荐的编程语言,其简洁的语法和丰富的特性大大提高了开发效率。在后续的学习中,可以探索 Kotlin 的泛型、扩展函数、协程等更高级的特性,以充分发挥 Kotlin 的潜力。
泛型
泛型类
在 Kotlin 中,我们可以定义泛型类,使其能够处理不同类型的数据。泛型类型参数用尖括号 <>
括起来。
class Box<T>(val value: T) {
fun getValue(): T {
return value
}
}
val intBox = Box(10)
val stringBox = Box("Hello")
println(intBox.getValue())
println(stringBox.getValue())
这里的 Box
类是一个泛型类,T
是类型参数。我们可以创建不同类型的 Box
对象,intBox
存储 Int
类型的值,stringBox
存储 String
类型的值。
泛型函数
除了泛型类,还可以定义泛型函数。
fun <T> printValue(value: T) {
println("The value is: $value")
}
printValue(15)
printValue("World")
printValue
函数是一个泛型函数,它可以接受任何类型的参数并打印出来。
泛型约束
有时候,我们希望对泛型类型参数进行一些限制,这就需要用到泛型约束。例如,我们可能希望某个泛型类型必须是某个类的子类。
open class NumberHolder<T : Number>(val number: T) {
fun getNumber(): T {
return number
}
}
val intHolder = NumberHolder(20)
val doubleHolder = NumberHolder(3.14)
// 下面这行代码会报错,因为String不是Number的子类
// val stringHolder = NumberHolder("Not a number")
这里 T : Number
表示 T
必须是 Number
类或其子类。
扩展函数
定义扩展函数
扩展函数允许我们在不修改类的源代码的情况下,为现有类添加新的函数。
fun String.addExclamationMark() = this + "!"
val greeting = "Hello"
val newGreeting = greeting.addExclamationMark()
println(newGreeting)
这里我们为 String
类定义了一个扩展函数 addExclamationMark
,它在字符串末尾添加一个感叹号。
扩展函数的作用域
扩展函数可以定义在顶层,也可以定义在类内部作为成员扩展函数。顶层扩展函数在整个项目中都可用,而成员扩展函数只能在包含它的类内部或其子类中使用。
class Outer {
fun String.insideOuter() = this + " from inside Outer"
fun callExtension() {
val str = "Hello"
println(str.insideOuter())
}
}
val outer = Outer()
outer.callExtension()
这里 insideOuter
是定义在 Outer
类内部的成员扩展函数,只能在 Outer
类内部调用。
数据类
数据类的定义
数据类是一种特殊的类,主要用于保存数据。Kotlin 会自动为数据类生成一些有用的方法,如 equals()
、hashCode()
、toString()
和 copy()
等。
data class User(val name: String, val age: Int)
val user1 = User("Bob", 28)
val user2 = User("Bob", 28)
println(user1 == user2)
println(user1)
val user3 = user1.copy(age = 29)
println(user3)
这里定义了一个 User
数据类,它有 name
和 age
两个属性。Kotlin 自动生成的 equals
方法比较两个 User
对象的属性值,toString
方法返回对象的字符串表示,copy
方法创建一个新的对象并可以修改部分属性值。
密封类
密封类的概念与定义
密封类用于表示受限的类继承结构,即一个密封类有一组有限的子类,并且这些子类都在与密封类相同的文件中声明。密封类使用 sealed
关键字定义。
sealed class Result
class Success : Result()
class Failure : Result()
fun handleResult(result: Result) {
when (result) {
is Success -> println("Operation successful")
is Failure -> println("Operation failed")
}
}
val successResult = Success()
val failureResult = Failure()
handleResult(successResult)
handleResult(failureResult)
这里 Result
是密封类,Success
和 Failure
是它的子类。在 handleResult
函数中,when
语句可以在不使用 else
分支的情况下处理所有可能的 Result
子类,因为编译器知道 Result
只有这两个子类。
协程
协程基础
协程是 Kotlin 中用于异步编程的强大工具。它允许我们以更简洁的方式编写异步代码,避免回调地狱。首先,需要引入协程库依赖。在 Gradle 中,可以这样添加:
implementation 'org.jetbrains.kotlinx:kotlinx - coroutines - core:1.6.4'
然后,可以使用 launch
函数启动一个协程:
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
delay(1000)
println("Hello from coroutine")
}
println("Hello from main")
}
这里 launch
函数创建并启动一个新的协程,delay
函数用于暂停协程执行指定的时间。runBlocking
函数用于阻塞主线程,直到所有子协程完成。
协程的并发与顺序执行
可以同时启动多个协程以实现并发执行,也可以按顺序执行协程。
fun main() = runBlocking {
val job1 = launch {
delay(1000)
println("Job 1 completed")
}
val job2 = launch {
delay(500)
println("Job 2 completed")
}
job1.join()
job2.join()
println("All jobs completed")
}
这里启动了两个协程 job1
和 job2
,它们并发执行,join
方法用于等待协程完成,确保所有协程完成后再打印 “All jobs completed”。
如果要按顺序执行,可以这样写:
fun main() = runBlocking {
launch {
delay(1000)
println("First task completed")
}.join()
launch {
delay(500)
println("Second task completed")
}.join()
println("All tasks completed")
}
协程的返回值
使用 async
函数可以启动一个有返回值的协程。
fun main() = runBlocking {
val deferred = async {
delay(1000)
42
}
val result = deferred.await()
println("The result is: $result")
}
这里 async
启动一个协程并返回一个 Deferred
对象,await
方法用于获取协程的返回值。
通过以上对 Kotlin 更多特性的介绍,你对 Kotlin 的理解应该更加深入了。无论是泛型带来的类型安全和代码复用,扩展函数的便捷性,数据类和密封类的特殊功能,还是协程在异步编程中的强大能力,都使得 Kotlin 成为一门功能丰富且高效的编程语言。在实际开发中,根据不同的需求和场景合理运用这些特性,可以编写出更加健壮、简洁和高效的代码。继续深入学习和实践,你将能够充分发挥 Kotlin 的潜力,开发出各种优秀的应用程序。例如在 Android 应用开发中,协程可以很好地处理网络请求、数据库操作等异步任务,提升用户体验;泛型和扩展函数可以优化代码结构,提高代码的可维护性和复用性。希望你在 Kotlin 的学习之旅中不断探索,收获更多编程乐趣和成果。