1.函数
// 普通函数写法
fun largeNum1(n1: Int, n2: Int): Int {
return max(n1, n2)
}
// 当函数体只有一行时简写,会自动推导出返回值
fun largeNum2(n1: Int, n2: Int) = max(n1, n2)
函数的默认参数使用
fun test(age: Int = 18, name: String) {
println("age is $age,name is $name")
}
fun main() {
test(name = "xiao")// 指定name的形式指定参数
}
2.if语句
// if语句有返回值,为if语句每一个条件中最后一行代码的返回值
fun largeNum3(n1: Int, n2: Int) = if (n1 > n2) n1 else n2
3.when语句
fun getScore(name: String) = when (name) {
"Tom" -> 86
"Jim" -> 77
"Jack" -> 95
else -> 0
}
// 使用is关键字来进行类型判定,类似Java的instanceof
fun checkNumber(num: Number) {
when (num) {
is Int -> println("int")
is Double -> println("double")
else -> println("not support")
}
}
4.for-in循环
fun testForIn1() {
for (i in 0..10) {// 0..10代表[0,10]闭区间
print("$i ")// 模板字符串,使用$取值
}
}
fun testForIn2() {
//until左闭右开[0, 10),step 2实现于i=i+2的效果
for (i in 0 until 10 step 2) {
print("$i ")// 结果:0 2 4 6 8
}
}
fun testForIn3() {
for (i in 10 downTo 0 step 2) {//downTo[10, 0]降序闭空间
print("$i ")// 结果:10 8 6 4 2 0
}
}
5.面向对象
(1).创建普通对象
class Person {
var name = ""
var age = 0
fun eat() {
println("$name is eating. He is $age years old")
}
}
fun main() {
// 创建对象无需new关键字
val p = Person()
p.name = "jack"
p.age = 18
p.eat()
}
(2)继承与构造函数
要想使用继承需满足两个条件:
- 使类可以被继承,在Kotlin中任何一个非抽象类默认都是不可以被继承的
方法:在class前面加上open关键字
open class Person {...}
- 使用冒号来进行继承,相当于Java中的extends
Kotlin将构造函数分成了两种:主构造函数和次构造函数
// 子类创建时调用Person类无参构造函数
class Student : Person() {
var sno = ""
var grade = 0
}
// 在创建实例时传入学号和年级,因此可声明为val(不可变)
class Student(val sno: String, val grade: Int) : Person() {
init {// init会在实例创建时自动调用
this.name = "xiao"
this.age = 18
}
}
将Person类改造,将name和age放入主构造函数内,这样改造后编译器将不会默认生成无参构造
open class Person(
private val name: String,// private权限,子类将无法直接访问该字段
private val age: Int // 在主构造函数中声明成val或者var的参数将自动成为该类的字段
) {
fun eat() {
println("$name is eating. He is $age years old")
}
}
class Student(val sno: String, val grade: Int, name: String, age: Int) : Person(
name,
age
) {// 类似于委托给父类的主构造函数,赋值
}
次构造函数:当一个类既有主构造函数又有次构造函数时,所有的次构造函数都必须调用主构造
函数(包括间接调用)
class Student(val sno: String, val grade: Int, name: String, age: Int) : Person(
name,
age
) {
constructor(name: String, age: Int) : this("", 8, name, age)
constructor() : this("xiao", 18)
}
特殊的情况:类中只有次构造函数,没有主构造函数
class Student : Person {
constructor(name: String, age: Int) : super(name, age)
}
(3)数据类
// 在class前加data关键字
data class CellPhone(val band: String, val price: Double)
fun main() {
val p1 = CellPhone("vivo", 128.8)
val p2 = CellPhone("vivo", 128.8)
// == 相当于Java中的equals;===相当于Java中的==,比较地址
println(p1 == p2) // true
}
(4)kotlin的单例模式
object Singleton {
fun singletonTest() {
println("singleton ...")
}
}
fun main() {
val s1 = Singleton
val s2 = Singleton
println(s1 === s2) // true,可知为同一个对象,即实现了单例
}
6.接口
interface Study {
fun readBooks()
fun doHomeWork()
fun doSomething() {// 默认实现函数,可不用重写
println("do something ...")
}
}
// 接口的实现同样也是使用冒号,因此直接在继承后面加逗号,写实现的接口
class Student(name: String, age: Int) : Person(name, age), Study {
override fun readBooks() {
println("$name is reading")
}
override fun doHomeWork() {
println("$name is doing homework")
}
}
7.kotlin修饰符范围
修饰符 | 范围 |
---|---|
internal | 相同模块的类可见 |
private | 当前类可见 |
protected | 当前类和子类可见 |
public | 所有类可见(默认修饰符) |
8.Lambda
(1)集合的创建和遍历
// 创建集合并遍历,指定泛型类型String,可限制容器元素类型
// listof创建的集合不可变,只能读取,不能对元素增加,删除,修改
val list = listOf<String>("apple", "banana", "orange")
for (fruit in list) {
print("$fruit ")
}
// 可变集合,mutableListOf
val list = mutableListOf<String>("apple", "banana", "orange")
// set集合使用方法同上
// 特点:Set集合中是不可以存放重复元素的,如果存放了多个相同的元素,只会保留其中一份
// map集合
val map = mapOf("Apple" to 1, "Banana" to 2, "Orange" to 3, "Pear" to 4, "Grape" to 5)
for ((fruit, number) in map) {
println("fruit is $fruit, number is $number")
}
(2)集合的函数式API
Lambda式的语法结构
{参数名1: 参数类型, 参数名2: 参数类型 -> 函数体}
val list = mutableListOf<String>("apple", "banana", "orange")
val minLengthFruit = list.minByOrNull { it.length }
println("名字最短的水果是:$minLengthFruit")
简化过程
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
val lambda = { fruit: String -> fruit.length }
val maxLengthFruit = list.maxBy(lambda)// 传入lambda表达式
// 1.开始简化
val maxLengthFruit = list.maxBy({ fruit: String -> fruit.length })
// 2.当Lambda参数是函数的最后一个参数时,可以将Lambda 表达式移到函数括号的外面
val maxLengthFruit = list.maxBy() { fruit: String -> fruit.length }
// 3.如果Lambda参数是函数的唯一一个参数的话,还可以将函数的括号省略
val maxLengthFruit = list.maxBy { fruit: String -> fruit.length }
// 4.Lambda表达式中的参数列表其实在大多数情况下不必声明参数类型
val maxLengthFruit = list.maxBy { fruit -> fruit.length }
// 5.当Lambda表达式的参数列表中只有一个参数时,也不必声明参数名,而是可以使用it关键字来代替
val maxLengthFruit = list.maxBy { it.length }
1.map映射
// 将每个集合元素映射成大写
val newList = list.map { it.uppercase() }
2.filter过滤数据
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
val newList = list.filter { it.length <= 5 }
.map { it.uppercase() }
for (fruit in newList) {
print("$fruit ")
}
3.any和all函数。其中any函数用于判断集合中是否至少存在一个元素满足指定条件,all函数用于判断集合中是否所有元素都满足指定条件(返回的是bool值)
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
val anyResult = list.any { it.length <= 5 }
val allResult = list.all { it.length <= 5 }
println("anyResult is $anyResult, allResult is $allResult")
4.let函数,将对象本身传入其中
fun doStudy(study: Study?) {// ?使传入的参数可为null
study?.let {// 如果study不为空时执行后续操作
it.doHomeWork()
it.readBooks()
}
}
9.协程
// 根据Dispatchers在不同的线程生成协程
// Default, Main, Unconfined, IO
suspend fun main() {
val job = CoroutineScope(Dispatchers.Default).launch {
println("Thread: ${Thread.currentThread().name}")
}
// 阻塞当前线程,防止job没执行完就退出
job.join()
}
10.flow
suspend fun main() {
val job = CoroutineScope(Dispatchers.Default).launch {
// 收集时才触发
numFlow()
.onCompletion { println("-------111---------") }
.collect {
println("value = $it thread = ${Thread.currentThread().name}")
}
// zip组合跟delay无关系
val nums = numFlow().onEach { delay(100) }
val names = nameFlow().onEach { delay(200) }
nums.zip(names) { num, name ->
"${num * 2} $name"
}.onCompletion { println("-------2222---------") }
.collect {
println("I am ${it}, thread = ${Thread.currentThread().name}")
}
// combine组合和delay有关系
nums.combine(names) { num, name ->
"${num * 2} $name"
}.onCompletion { println("-------3333---------") }
.collect {
println("I am ${it}, thread = ${Thread.currentThread().name}")
}
}
job.join()
}
suspend fun numFlow() = flow<Int> {
for (i in 1..3) {
emit(i)
}
}
suspend fun nameFlow() = flow<String> {
for (i in listOf("ww", "uu", "kk")) {
emit(i)
}
}
结果:
value = 1 thread = DefaultDispatcher-worker-1
value = 2 thread = DefaultDispatcher-worker-1
value = 3 thread = DefaultDispatcher-worker-1
-------111---------
I am 2 ww, thread = DefaultDispatcher-worker-2
I am 4 uu, thread = DefaultDispatcher-worker-1
I am 6 kk, thread = DefaultDispatcher-worker-1
-------2222---------
I am 2 ww, thread = DefaultDispatcher-worker-1
I am 4 ww, thread = DefaultDispatcher-worker-1
I am 6 ww, thread = DefaultDispatcher-worker-1
I am 6 uu, thread = DefaultDispatcher-worker-1
I am 6 kk, thread = DefaultDispatcher-worker-1
-------3333---------