前言
该内容是对《第一行代码》第3版kotlin基础知识的总结
kotlin基础知识
一、变量和函数
(一)变量
- val(value的简写)用来声明一个不可变的变量,这种变量在初始赋值之后就再也不能重新赋值,对应java中的final变量。
- var(variable的简写)用来声明一个可变的变量,这种变量在初始赋值之后仍然可以再被重新赋值,对应java中的非final变量。
- kotlin拥有类型推导机制
fun main() {
val a = 10
println("a = " + a)
}
- 如果对对一个变量延迟赋值,则需要显示地声明变量类型
val a: Int = 10
Java基本数据类型 | Kotlin对象数据类型 | 数据类型说明 |
---|---|---|
int | Int | 整型 |
long | Long | 长整型 |
short | Short | 短整型 |
float | float | 单精度浮点型 |
double | Double | 双精度浮点型 |
boolean | Boolean | 布尔值 |
char | Char | 字符型 |
byte | Byte | 字节型 |
永远优先使用val,当val无法满足需求时改用var,这样设计出来的程序会更加健壮,也更加符合高质量的编码规范
(二)函数
fun methodName(param1: Int, param2: Int): Int {
return 0
}
- fun是定义函数的关键字
- fun后面紧跟着函数名
- 函数名后面紧跟着参数列表,参数的声明格式是“参数名:参数类型”
- 参数后面那部分是可选的,用于声明函数返回什么类型的数据,如果函数不需要返回数据,则这部分不写
- 最后2个大括号之间的是函数体
当一个函数只有一行时,可以直接将唯一一行代码写在函数定义的尾部,中间用等号连接即可
fun largerNumber(num1: Int, num2: Int) : Int = max(num1, num2)
二、程序的逻辑控制
if条件语句
kotlin中的if语句和java中的if语句几乎没有区别:
fun largerNumber(num1: Int, num2: Int): Int {
var value = 0
if(num1 > num2) {
value = num1
}else {
value = num2
}
return value
}
kotlin中的if语句可以把每个条件的最后一行代码作为返回值
fun largerNumber(num1: Int, num2: Int): Int {
return if(num1 > num2) {
num1
}else{
num2
}
}
when条件语句
when允许传入一个任意类型的参数,然后可以在when的结构体中定义一系列的条件,格式是:匹配值 -> {执行逻辑}
当执行逻辑只有一行代码时,{ }可以省略
fun getScore(name: String) = when (name) {
"Tom" -> 86
"Jim" -> 77
"Jack" -> 95
"Lily" -> 100
else -> 0
}
除了精确匹配之外,when还允许类型匹配
fun checkNumber(num: Number) {
when (num) {
is Int -> println("number is Int")
is Double -> println("number is Double")
else -> println("number not support")
}
}
when语句还有一种不带参数的用法:
fun getScore(name: String) = when {
name == "Tom" -> 86
name == "Jim" -> 77
name == "Jack" -> 95
name == "Lily" -> 100
else -> 0
}
循环语句
- while循环用法与java相同
- java中的for-i循环在kotlin中直接被舍弃了,而Java中另一种for-each循环则被Kotlin进行了大幅度的加强,变成了for-in循环
for-in
- 可以用如下语法表示一个区间:
相当于数学上的[0,10]val range = 0 .. 10
- 可以用for-in循环来遍历这个区间
fun main() { for (i in 0 .. 10) { println(i) } }
- 可以用until创建一个左闭右开区间(最为常用)
- 如果想要跳过一些元素,可以使用step 关键字:
fun main() { for (i in 0 until 10 step 2) { println(i) } }
- 可以使用downTo(闭区间)来创建一个降序的区间
fun main() { for(i in 10 downTo 1) { println(i) } }
三、面向对象编程
类与对象
定义一个类:
class Person {
var name = ""
var age = 0
fun eat() {
println("$name is eating. He is $age years old.")
}
}
实例化对象:
val p = Person()
继承与构造函数
继承
kotlin默认的类都是不可继承的,需要加上open
open class Person{}
java中继承的关键字是extends,而在Kotlin中变成了一个冒号
class Student : Person() {
var sno = ""
var grade = 0
}
主构造函数
主构造函数是最常用的构造函数,每个类默认都会有一个不带参的主构造函数,主构造函数的特点是没有函数体,直接定义在类名的后面即可
class Student(val sno: String, val grade: Int) : Person() {}
主构造函数没有函数体,如果想在主构造函数中实现一些逻辑,可以写在init结构体中
class Student(val sno: String, val grade: Int) : Person() {
init{
println("test")
}
}
次构造函数
- 一个类只能有一个主构造函数,但是可以有多个次构造函数
- 当一个类既有主构造函数,又有次构造函数时,所有的次构造函数都必须调用主构造函数
class Student(val sno: String, val grade: Int, name: String, age: Int) : Person(name, age) { constructor(name: String, age: Int) : this("", 0, name, age) {} constructor() : this("", 0) {} }
- 一个类可以没有主构造函数但有次构造函数
接口
与java相同
四、可见性修饰符
- public: 表示对所有类都可见,Kotlin中public修饰符是默认的
- private:表示只对当前类内部可见
- protected:表示对当前类和子类可见
- internal:同一模块内部的类可见
五、数据类和单例类
数据类
在kotlin中创建数据类使用data关键字,kotlin会根据主构造函数中的参数自动生成equals()、hashCode()等固定且无实际逻辑意义的函数
data class Cellphone(val brand: String, val price: Double)
单例类
在kotlin中创建单例类使用object关键字
object Singleton {
fun test() {}
}
Singleton是一个单例类,调用单例类中的函数:
Singleton.test()
这种写法看上去像是静态方法的调用,实际上kotlin为我们生成了一个类的实例,并且保证全局只有一个。
六、Lambda编程
Lambda的语法结构:
{参数名1: 参数类型, 参数名2: 参数类型 -> 函数体}
集合的函数式API
- maxBy
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon") val maxLengthFruit = list.maxBy { it.length }
- map
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon") val newList = list.map { it.toUpperCase() }
- filter
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon") val newList = list.filter { it.length <= 5 }
匿名内部类
以创建线程为例:
Thread(object: Runnable {
ovveride fun run() {
}
})
Java函数式API的使用
如果我们在Koltin代码中调用了一个Java方法,并且该方法接收一个Java单抽象方法接口参数,就可以使用函数式API
Thread {
println("Thread is running")
}.start()
let
let属于Kotlin中的标准函数
obj.let { obj2 ->
}
obj对象会作为参数传入Lambda表达式中,即obj就是obj2,这就是let的作用
let配合?.进行代码优化
- 优化前:
fun doStudy(study: Study?) { if(study != null) { study.readBooks() } if(study != null) { study.doHomework() } }
- 优化后:
fun doStudy(study: Study?) { study?.let { it.readBooks() it.doHomework() } }
七、Kotlin中的小特性
字符串内嵌表达式
Kotlin中字符串内嵌表达式的语法规则:
“Hello, ${obj.name}. nice to meet you!”
Kotlin允许在字符串中嵌入${}这种语法结构的表达式,并在允许时使用表达式执行的结构替代这一部分的内容
函数的参数默认值
Kotlin可以为函数的参数设定默认值
fun test(num: Int, str: String = "hello") {
}
如果给第一个参数num设定默认值
fun test(num: Int = 100, str: String") {
}
调用时应该通过键值对的方式来传参
test(str = "hello", num = 10)
这样就不必向传统写法那样按照参数定义的顺序来传参