前言
本专栏基于郭霖第一行代码第三版Kotlin知识编写,在此仰慕+感谢大佬,当初就是为了学习Kotlin买的这本书,果然大佬讲东西还是通俗易懂~彩虹屁安排一波🌈
这个专栏我会将本人学习到的关于Kotlin知识顺序渐进通俗的输出一遍,相信各位大佬看了之后一定会直呼牛批!
下面有请各位大佬观看通俗易懂Kotlin系列之第一篇文章——变量和函数
第一篇文章首先了解 变量、 函数、 逻辑控制语句、 面向对象 、lambda、 空指针处理 、内嵌表达式等知识
1:变量
1.1:val和var
val(value)用来声明一个不可变的变量,对应java中的final
var(variable)用来声明一个可变的变量,对应java中的非final
在Java中一个良好的编程习惯是:除非一个变量被明确允许被修改否则他都应该被加上final变量
同样的在kotlin中为了保持代码的健壮性,我们都应该首先使用val来声明一个变量,在没有变法满足需求的时候再使用var
1.2:Kotlin中的类型推导机制
fun main() {
val data = 10
println("data的值是$data")
}
我们使用声明data赋值为10 kotlin会自动将data推导为整形变量
这时候就应该这样写:
val data1: Int = 10
println(data1)
1.3:Java和Kotlin数据类型对照表
2:函数
2.1:fun(function)是定义函数关键字,无论定义什么函数都需要使用fun来声明
我们只要掌握以下命名规范就可以掌握80%的编程场景
fun methodTest(num1: Int, num2: Int): Int {
return max(num1, num2)
}
当函数中的代码只有一行代码的时候可以不用编写代码体,直接写在代码后边即可
fun methodTest(num1: Int, num2: Int): Int = max(num1, num2)
由于Kotlin有出色的类型推到机制 max函数返回必定是Int类型,因此我们可以继续简化代码
fun methodTest(num1: Int, num2: Int) = max(num1, num2)
3:逻辑控制语句
程序的执行语句主要分为三种:顺序语句、条件语句、循环语句
3.1:if条件语句
if语句kotlin和java没什么太大的区别,下面演示一段条件语句在Kotlin中如何使用和简化
fun getNum(num1: Int, num2: Int): Int {
var result = 0
if (num1 > num2) {
result = num1
} else {
result = num2
}
return result
}
简化
fun getNum2(num1: Int, num2: Int): Int {
var result = if (num1 > num2) {
num1
} else {
num2
}
return result
}
再简化
fun getNum2(num1: Int, num2: Int): Int {
return if (num1 > num2) {
num1
} else {
num2
}
}
我们上边说过代码体中只有一段代码的时候可以不写函数体 直接用=链接即可,另外kotlin有出色类型推导机制这里可以将Int直接省略 如下最终代码为:
fun getNum2(num1: Int, num2: Int) = if (num1 > num2) {
num1
} else {
num2
}
3.2:when条件语句
kotlin中的when语句跟java中的switch差不多,但是又比switch强大...
fun whenTest(name: String) = when (name) {
"jingkai" -> 88
"jingxiaokai" -> 100
else -> 0
}
或者使用
fun whenTest2(name: String) = when {
name == "Tom" -> 82
name == "Jim" -> 11
name == "Cha" -> 12
else -> 0
}
另外也kotlin中的when也可以用来判断类型:
fun checkNum(num: Number) = when (num) {
is Int -> println("是int")
is Double -> println("是Double")
else -> println("什么也不是")
}
is相当于java中的instanceof关键字
3.3:循环语句
for-in循环
区间:
0..10 代表0到10的闭区间
0 until 10 代表0到10 的左闭右开区间
fun forTest() {
for (i in 0 until 10 step 2) {
}
}
如上代码代表在0到10的区间内每次都增加2,也就是使用step跳过复杂的逻辑
如果想要实现降序 可以使用 downto关键字
fun forTest() {
for (i in 0 downTo 10 step 2) {
}
}
4:面向对象编程
4.1:类与对象
在kotlin中创建对象
fun classTest() {
val data = Data("jingkais", 1)
data.height="178"
data.weight="77"
}
4.2:继承与构造函数
Kotlin中的继承可以这样写 使用open声明一个类可以被继承 ,:表示 Student继承自Person
open class Person(val name: String,val age: Int) {
}
class Student( name: String, age: Int) : Person(name, age) {
}
kotlin将构造函数分为了两种 主构造函数 和 次构造函数
主构造函数没有函数体直接写类名后边即可 声明和使用如下
因为在主构造函数中没有函数体 我们可以使用init函数来执行其它逻辑语句
class Student( name: String, age: Int) : Person(name, age) {
init {
//书写逻辑
}
}
val student = Student("jingkais", 18)
次构造函数:
kotlin规定当一个类中机有主构造函数又有次构造函数时,所有的次构造函数都必须调用主构造函数
kotlin次构造函数用constructor关键字来定义的
class Student(name: String, age: Int) : Person(name, age) {
init {
//书写逻辑
}
constructor() : this("", 0)
constructor(height: String, wight: String) : this("", 0)
}
另一种情况:只有次构造函数没有主构造函数
class Student : Person {
constructor(name: String, age: Int) : super(name, age) {
}
}
4.3:接口
kotlin中的接口跟java中的接口没有任何区别
interface StudyEnglish {
fun doHomeWork()
fun readBooks()
}
//调用
class Student : Person("", 1), StudyEnglish {
override fun doHomeWork() {
TODO("Not yet implemented")
}
override fun readBooks() {
TODO("Not yet implemented")
}
}
4.4:java和kotlin函数可见修饰符对照表
4.5:数据类与单列类
Kotlin中新建数据类 就是我们平常所说的的bean可以直接新建 包→New→Kotlin File/Class/Data class
data class Data(val name: String, val age: Int) {
}
并且kotlin会帮你将equals() hashCode() toString() 等固定且无实际意义的的方法自动生成
单列模式用于避免重复创建对象 减少资源的浪费
在kotlin中创建单列类十分简单 →New→Kotlin File/Object
object Singleton {
fun singleTest() {
println("单列类")
}
}
4.6:Lambda编程
lambda分为基础知识、高阶函数、DSL等高级Lambda技巧
4.6.1:集合的创建与遍历
kotlin提供了内置listof(不可变)mutableListOf(可变)新建一个集合
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape")
val list = mutableListOf("Apple", "Banana", "Orange", "Pear", "Grape")
set不可以存放重复的数据,同样set也存在 mutableSetOf(可变)
val set = setOf("Apple", "Banana", "Orange", "Pear", "Grape")
map集合,同样map也存在 mutableMapOf(可变)
val map = mapOf("Apple" to 1, "Banana" to 2, "Orange" to 3, "Pear" to 4, "Grape" to 5)
4.6.2:集合的函数式api
现在有一个需求:找到集合中单词最长的水果名 我们可以写出如下代码:
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
var maxLengthFruit = ""
for (fruit in list) {
if (fruit.length > maxLengthFruit.length) {
maxLengthFruit = fruit
}
}
println("max length fruit is " + maxLengthFruit)
使用集合的函数式api可以简化成如下
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
val maxLengthFruit = list.maxBy { it.length }
println("max length fruit is " + maxLengthFruit)
上边代码用到了Lambda表达式 ,我们来理解一下lanbda表达式的定义:一段可以作为参数传递的代码,语法结构如下:
{参数名1: 参数类型, 参数名2: 参数类型 -> 函数体}
可以声明参数列表,参数列表结尾使用->符号表示参数列表的开始和函数体的开始,函数体重可以编写任意行代码(不建议写得太长),并且最后一行代码自动作为Lambda表达式的返回值
下边来解释一下上边的代码:
maxBy函数是一个普通函数,他接受一个Lambda 只不过他在遍历集合的时候会将每次遍历的值传递到Lambda中,
他的工作原理就是根据我们传入的条件来遍历集合 所以我们代码可以写成如下:
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
val lambda = { fruit: String -> fruit.length }
val maxLengthFruit = list.maxBy(lambda)
定义的lambda表达式如上所示,我们还可以继续简化代码 将Lambda直接放入到maxBy中:
val maxLengthFruit = list.maxBy({ fruit: String -> fruit.length })
kotlin规定当Lambda参数是函数的最后一个参数可以将Lambda移出到()外边
val maxLengthFruit = list.maxBy() { fruit: String -> fruit.length }
接下来如果lambda 参数是函数的唯一一个参数的话还可以省略括号
val maxLengthFruit = list.maxBy{ fruit: String -> fruit.length }
Lambda表达式中大多情况下不必进行参数类型声明:
val maxLengthFruit = list.maxBy{ fruit -> fruit.length }
另外如果代码中只有一个参数也可以不用声明参数名:
val maxLengthFruit = list.maxBy { it.length }
牛逼不牛逼吧 ,看管你湿了吗
另外集合中的map函数是最常用的一种函数式API,他用于将集合中的每个元素都映射成另一个值,映射规则根据Lambda来定
如果我们希望使集合中水果名都转化为大写:
fun main() {
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
val newList = list.map { it.toUpperCase() }
for (fruit in newList) {
println(fruit)
}
}
4.6.3:函数式api all和any
all判断集合中所有元素都满足指定条件
any判断集合中的元素至少有一个元素满足条件
fun main() {
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.5:空指针检查
4.5.1:可空系统类型
在对象后添加?表示这个对象可能是空,使用对象的时候需要添加?.来进行判断 表示是空不执行,否则执行
fun doStudy(study: Study?) {
study?.readBooks()
study?.doHomework()
}
4.5.2: 判空辅助工具
编写函数来获取一段文本的长度使用传统的写法
fun getTextLength(text: String?): Int {
if (text != null) {
return text.length
}
return 0
}
借助操作符变得更简单
?:操作符。这个操作符的左右两边都接收一个表达式,
如果左边表达式的结果不为空就返回左边表达式的结果,否则就返回右边表达式的结果。
fun getTextLength(text: String?) = text?.length ?: 0
!! 告诉Kotlin,我非常确信这里的对象不会为空,但是出现问题我会自己承担
fun printUpperCase() {
val upperCase = content!!.toUpperCase()
println(upperCase)
}
4.5.3: let标准函数
fun doStudy(study: Study?) {
study?.readBooks()
study?.doHomework()
}
上边的函数可以使用let函数进行优化 如下
fun doStudy(study: Study?) {
study?.let { stu ->
stu.readBooks()
stu.doHomework()
}
}
lambda表达式如下
fun doStudy(study: Study?) {
study?.let {
it.readBooks()
it.doHomework()
}
}
4.6:字符串内嵌表达式
val brand = "Samsung"
val price = 1299.99
println("Cellphone(brand=" + brand + ", price=" + price + ")")
使用内嵌表达式如下
val brand = "Samsung"
val price = 1299.99
println("Cellphone(brand=$brand, price=$price)")
同样也可以使用如下${函数}直接对函数进行拼接
println("lambda表达式高阶函数返回的数据是${resultMinus}")
val resultMinus = num1AndNum2(num1, num2) { n1, n2 ->
n1 - n2
}
4.7:函数的默认表达式
表示一个函数的参数允许存在默认值 这样我们调用的时候可以不传已经存在的值,默认调用默认存在的值
fun printParams(num: Int, str: String = "hello") {
println("num is $num , str is $str")
}
fun main() {
printParams(123)
}
//也可以使用键值对匹配的方式添加数据,意思就是可以不按照函数中的参数排列方式进行传参,只要键值对对应就可以
printParams(str = "world", num = 123)
好了关于变量和函数相关的知识告一段落下一篇文章我会输出关于Kotlin的标准函数和静态方法等相关知识~
点赞加关注!学习不迷路!😬😬😬😬😬😬😬😬😬😬
有什么问题欢迎留言指出😜😜😜😜😜😜😜😜😜😜