Kotlin:变量和函数

kotlin&android.png

前言

本专栏基于郭霖第一行代码第三版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推导为整形变量

运行之后如我们所料
image.png
但是Koltin中的类型推导并不是总是正常工作,比如我们在对一个变量进行延时赋值的时候Kotlin就无法进行类型推导了

这时候就应该这样写:

    val data1: Int = 10
    println(data1)

1.3:Java和Kotlin数据类型对照表

image.png

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函数可见修饰符对照表

image.png

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的标准函数和静态方法等相关知识~
点赞加关注!学习不迷路!😬😬😬😬😬😬😬😬😬😬
有什么问题欢迎留言指出😜😜😜😜😜😜😜😜😜😜

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容