美文网首页
kotlin基础之变量与函数详解

kotlin基础之变量与函数详解

作者: 安安_660c | 来源:发表于2023-02-20 15:59 被阅读0次

    编程语言之多,让人眼花缭乱。你可能不知道,世界上一共诞生过600多门有记录的编程语言, 没有记录的那就更多了。这些编程语言基本上共有的特性就是变量和函数。可以说,变量和函 数就是编程语言之本。那么本节我们就来学习一下Kotlin中变量和函数的用法。

    1.变量

    先来学习变量。在Kotlin中定义变量的方式和Java区别很大,在Java中如果想要定义一个变 量,需要在变量前面声明这个变量的类型,比如说int a表示a是一个整型变量,String b表 示b是一个字符串变量。而Kotlin中定义一个变量,只允许在变量前声明两种关键字:val和 var。

    val(value的简写)用来声明一个不可变的变量,这种变量在初始赋值之后就再也不能重新赋 值,对应Java中的final变量。

    var(variable的简写)用来声明一个可变的变量,这种变量在初始赋值之后仍然可以再被重新 赋值,对应Java中的非final变量。

    如果你有Java编程经验的话,可能会在这里产生疑惑,仅仅使用val或者var来声明一个变量, 那么编译器怎么能知道这个变量是什么类型呢?这也是Kotlin比较有特色的一点,它拥有出色的 类型推导机制。

    举个例子,我们在上一章的创建的kt文件中,编写如下代码:

    fun main() {
        val a = 10
        println("a = " + a)
    } 
    

    注意,Kotlin每一行代码的结尾是不用加分号的,如果你写惯了Java的话,在这里得先熟悉一 下。

    在上述代码中,我们使用val关键字定义了一个变量a,并将它赋值为10,这里a就会被自动推 导成整型变量。因为既然你要把一个整数赋值给a,那么a就只能是整型变量,而如果你要把一 个字符串赋值给a的话,那么a就会被自动推导成字符串变量,这就是Kotlin的类型推导机制。

    现在我们运行一下main()函数,执行结果如下图1所示,正是我们所预期的。

    图1.png

    但是Kotlin的类型推导机制并不总是可以正常工作的,比如说如果我们对一个变量延迟赋值【1】的 话,Kotlin就无法自动推导它的类型了。这时候就需要显式地声明变量类型才行,Kotlin提供了 对这一功能的支持,语法如下所示:

    【1】变量延迟赋值:立即赋值是将等号右边的表达式计算过后再赋给式子的左边,延迟赋值则是不计算右边的式子,在后续代码中要调用左侧的变量时才计算。

    val a: Int = 10 
    

    可以看到,我们显式地声明了变量a为Int类型,此时Kotlin就不会再尝试进行类型推导了。如 果现在你尝试将一个字符串赋值给a,那么编译器就会抛出类型不匹配的异常。

    如果你学过Java并且足够细心的话,你可能发现了Kotlin中Int的首字母是大写的,而Java中 int的首字母是小写的。不要小看这一个字母大小写的差距,这表示Kotlin完全抛弃了Java中的 基本数据类型,全部使用了对象数据类型。在Java中int是关键字,而在Kotlin中Int变成了一 个类,它拥有自己的方法和继承结构。下表中列出了Java中的每一个基本数据类型在Kotlin中 对应的对象数据类型。

    图1.png

    接下来我们尝试对变量a进行一些数学运算,比如说让a变大10倍,可能你会很自然地写出如下 代码:

    fun main() {
    val a: Int = 10
    a = a * 10
    println("a = " + a)
    } 
    

    很遗憾,如果你这样写的话,编译器一定会提示一个错误:Val cannot be reassigned。这是 在告诉我们,使用val关键字声明的变量无法被重新赋值。出现这个问题的原因是我们在一开始 定义a的时候将它赋值成了10,然后又在下一行让它变大10倍,这个时候就是对a进行重新赋值 了,因而编译器也就报错了。

    解决这个问题的办法也很简单,前面已经提到了,val关键字用来声明一个不可变的变量,而 var关键字用来声明一个可变的变量,所以这里只需要把val改成var即可,如下所示:

    fun main() {
    var a: Int = 10
    a = a * 10
    println("a = " + a)
    } 
    

    现在编译器就不会再报错了,重新运行一下代码,结果下图所示。

    图1.png

    可以看到a的值变成了100,这说明我们的数学运算操作成功了。

    这里你可能会产生疑惑:既然val关键字有这么多的束缚,为什么还要用这个关键字呢?干脆全 部用var关键字不就好了。其实Kotlin之所以这样设计,是为了解决Java中final关键字没有被 合理使用的问题。

    在Java中,除非你主动在变量前声明了final关键字,否则这个变量就是可变的。然而这并不 是一件好事,当项目变得越来越复杂,参与开发的人越来越多时,你永远不知道一个可变的变 量会在什么时候被谁给修改了,即使它原本不应该被修改,这就经常会导致出现一些很难排查 的问题。因此,一个好的编程习惯是,除非一个变量明确允许被修改,否则都应该给它加上 final关键字。

    但是,不是每个人都能养成这种良好的编程习惯。我相信至少有90%的Java程序员没有主动在 变量前加上final关键字的意识,仅仅因为Java对此是不强制的。因此,Kotlin在设计的时候就 采用了和Java完全不同的方式,提供了val和var这两个关键字,必须由开发者主动声明该变量 是可变的还是不可变的。

    那么我们应该什么时候使用val,什么时候使用var呢?这里我告诉你一个小诀窍,就是永远优 先使用val来声明一个变量,而当val没有办法满足你的需求时再使用var。这样设计出来的程 序会更加健壮,也更加符合高质量的编码规范。 不少刚接触编程的人对于函数和方法这两个概念有些混淆,不明白它们有什么区别。其实,函 数和方法就是同一个概念,这两种叫法都是从英文翻译过来的,函数翻译自function,方法翻 译自method,它们并没有什么区别,只是不同语言的叫法习惯不一样而已。而因为Java中方 法的叫法更普遍一些,Kotlin中函数的叫法更普遍一些,因此本书里可能会交叉使用两种叫法, 你只要知道它们是同一种东西就可以了,不用在这个地方产生疑惑。 函数是用来运行代码的载体,你可以在一个函数里编写很多行代码,当运行这个函数时,函数 中的所有代码会全部运行。像我们前面使用过的main()函数就是一个函数,只不过它比较特 殊,是程序的入口函数,即程序一旦运行,就是从main()函数开始执行的。 但是只有一个main()函数的程序显然是很初级的,和其他编程语言一样,Kotlin也允许我们自 由地定义函数,语法规则如下:

    2.函数

    不少刚接触编程的人对于函数和方法这两个概念有些混淆,不明白它们有什么区别。其实,函 数和方法就是同一个概念,这两种叫法都是从英文翻译过来的,函数翻译自function,方法翻 译自method,它们并没有什么区别,只是不同语言的叫法习惯不一样而已。而因为Java中方 法的叫法更普遍一些,Kotlin中函数的叫法更普遍一些,因此本书里可能会交叉使用两种叫法, 你只要知道它们是同一种东西就可以了,不用在这个地方产生疑惑。

    函数是用来运行代码的载体,你可以在一个函数里编写很多行代码,当运行这个函数时,函数 中的所有代码会全部运行。像我们前面使用过的main()函数就是一个函数,只不过它比较特 殊,是程序的入口函数,即程序一旦运行,就是从main()函数开始执行的。

    但是只有一个main()函数的程序显然是很初级的,和其他编程语言一样,Kotlin也允许我们自 由地定义函数,语法规则如下:

    fun methodName(param1: Int, param2: Int): Int {
    return 0
    } 
    

    下面我来解释一下上述的语法规则,首先fun(function的简写)是定义函数的关键字,无论你 定义什么函数,都一定要使用fun来声明。

    紧跟在fun后面的是函数名,这个就没有什么要求了,你可以根据自己的喜好起任何名字,但是 良好的编程习惯是函数名最好要有一定的意义,能表达这个函数的作用是什么。

    函数名后面紧跟着一对括号,里面可以声明该函数接收什么参数,参数的数量可以是任意多个,例如上述示例就表示该函数接收两个Int类型的参数。参数的声明格式是“参数名: 参数类型”,其中参数名也是可以随便定义的,这一点和函数名类似。如果不想接收任何参数,那么写一对空括号就可以了。

    参数括号后面的那部分是可选的,用于声明该函数会返回什么类型的数据,上述示例就表示该函数会返回一个Int类型的数据。如果你的函数不需要返回任何数据,这部分可以直接不写。最后两个大括号之间的内容就是函数体了,我们可以在这里编写一个函数的具体逻辑。由于上述示例中声明了该函数会返回一个Int类型的数据,因此在函数体中我们简单地返回了一个0。

    这就是定义一个函数最标准的方式了,虽然Kotlin中还有许多其他修饰函数的关键字,但是只要掌握了上述函数定义规则,你就已经能应对80%以上的编程场景了,至于其他的关键字,我们会在后面慢慢学习。

    接下来我们尝试按照上述定义函数的语法规则来定义一个有意义的函数,如下所示:

     fun largerNumber(num1: Int, num2: Int): Int {
            return max(num1, num2)
    } 
    

    这里定义了一个名叫test()的函数,该函数的作用很简单,接收两个整型参数,然 后总是返回两个参数中更大的那个数。

    注意,上述代码中使用了一个max()函数,这是Kotlin提供的一个内置函数,它的作用就是返回 两个参数中更大的那个数,因此我们的test()函数其实就是对max()函数做了一层 封装而已。

    现在你可以开始在LearnKotlin文件中实现test()这个函数了,当你输入“max”这 个单词时,Android Studio会自动弹出如下图所示的代码提示。

    图1.png

    Android Studio拥有非常智能的代码提示和补全功能,通常你只需要键入部分代码,它就能自动预测你想要编写的内容,并给出相应的提示列表。我们可以通过上下键在提示列表中移动,然后按下“Enter”键,Android Studio就会自动帮我们进行代码补全了。

    这里我非常建议你经常使用Android Studio的代码补全功能,可能有些人觉得全部手敲更有成就感,但是我要提醒一句,使用代码补全功能后,Android Studio不仅会帮我们补全代码,还会帮我们自动导包,这一点是很重要的。比如说上述的max()函数,如果你全部手敲出来,那么这个函数一定会提示一个红色的错误,如下图所示。

    图1.png

    出现这个错误的原因是你没有导入max()函数的包。当然,导包的方法也有很多种,你将光标 移动到这个红色的错误上面就能看到导包的快捷键提示,但是最好的做法就是使用Android Studio的代码补全功能,这样导包工作就自动完成了。

    现在我们使用代码补全功能(alt+enter)再来编写一次max()函数,你会发现LearnKotlin文件的头部自动导入了一个max()函数的包,并且不会再有错误提示了,如下图所示。

    图1.png

    现在test()函数已经编写好了,接下来我们可以尝试在main()函数中调用这个函数,并且实现在两个数中找到较大的那个数这样一个简单的功能,代码如下所示:

    fun main() {
            val a = 37
            val b = 43
            var value :Int
            value = test(a, b)
            println("larger number is " + value)
    }
    
    fun test(int1: Int,int2: Int): Int {
        return max(int1,int2)
    } 
    

    这段代码很简单,我们定义了a、b两个变量,a的值是37,b的值是40,然后调用test()函数,并将a、b作为参数传入。test()函数会返回这两个变量中较大的那个数,最后将返回值打印出来。现在运行一下代码,结果下图所示。程序正如我们预期的那样运行了。

    图1.png

    这就是Kotlin中最基本也是最常用的函数用法,虽然这里我们实现的largerNumber()函数很 简单,但是掌握了函数的定义规则之后,你想实现多么复杂的函数都是可以的。

    3.拓展内容

    我们再来学习一个Kotlin函数的语法糖,这个语法糖在以后的开发中会起到相当重要的作用。

    当一个函数中只有一行代码时,Kotlin允许我们不必编写函数体,可以直接将唯一的一行代码写在函数定义的尾部,中间用等号连接即可。比如我们刚才编写的test()函数就只有一行代码,于是可以将代码简化成如下形式:

    fun main() {
            val a = 37
            val b = 43
            var value  = test(a, b)
            println("larger number is " + value)
    }
    
    //注意看这里,原定义的函数变成只有1行了
    fun test(int1: Int,int2: Int): Int =  max(int1,int2) 
    

    使用这种语法,return关键字也可以省略了,等号足以表达返回值的意思。另外,还记得Kotlin出色的类型推导机制吗?在这里它也可以发挥重要的作用。由于max()函数返回的是一个Int值,而我们在test()函数的尾部又使用等号连接了max()函数,因此Kotlin可以推导出test()函数返回的必然也是一个Int值,这样就不用再显式地声明返回值类型了,代码可以进一步简化成如下形式:

    fun test(int1: Int,int2: Int) =  max(int1,int2) 
    
    

    可能你会觉得,函数只有一行代码的情况并不多嘛,这个语法糖也不会很常用吧?其实并不是这样的,因为它还可以结合Kotlin的其他语言特性一起使用,对简化代码方面的帮助很大,后面我们会慢慢学习它更多的使用场景。

    高级Kotlin强化实战

    第一章 Kotlin入门教程

    • Kotlin 概述

    • Kotlin 与 Java 比较

    • 巧用 Android Studio

    • 认识 Kotlin 基本类型

    • 走进 Kotlin 的数组

    • 走进 Kotlin 的集合

    • 集合问题

    • 完整代码

    • 基础语法

    1.png

    第二章 Kotlin 实战避坑指南

    • 方法入参是常量,不可修改

    • 不要 Companion 、INSTANCE ?

    • Java 重载,在 Kotlin 中怎么巧妙过渡一下?

    • Kotlin 中的判空姿势

    • Kotlin 复写 Java 父类中的方法

    • Kotlin “狠”起来,连TODO 都不放过!

    • is、as` 中的坑

    • Kotlin 中的 Property 的理解

    • also 关键字

    • takeIf 关键字

    • takeIf 关键字

    • 单例模式的写法

    2.png

    第三章 项目实战《Kotlin Jetpack 实战》

    • 从一个膜拜大神的 Demo 开始

    • Kotlin 写 Gradle 脚本是一种什么体验?

    • Kotlin 编程的三重境界

    • Kotlin 高阶函数

    • Kotlin 泛型

    • Kotlin 扩展

    • Kotlin 委托

    • 协程“不为人知”的调试技巧

    • 图解协程:suspend

    3.png

    s信获取zi料~

    相关文章

      网友评论

          本文标题:kotlin基础之变量与函数详解

          本文链接:https://www.haomeiwen.com/subject/fdvikdtx.html