kotlin 知识点一 变量和函数

news/2025/2/25 21:50:16

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

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

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

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

举个例子,我们打开上一节创建的LearnKotlin 文件,在main()函数中编写如下代码:

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

注意,Kotlin每一行代码的结尾是不用加分号的,如果你写惯了Java 的话,在这里得先熟悉一
下。
在上述代码中,我们使用val关键字定义了一个变量a,并将它赋值为10 ,这里a就会被自动推
导成整型变量。因为既然你要把一个整数赋值给a,那么a就只能是整型变量,而如果你要把一
个字符串赋值给a的话,那么a就会被自动推导成字符串变量,这就是Kotlin的类型推导机制。
现在我们运行一下main()函数,执行结果如图所示,正是我们所预期的。

在这里插入图片描述

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

val a: Int = 10 

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

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

表中列出了Java 中的每一个基本数据类型在Kotlin中对应的对象数据类型。

在这里插入图片描述

接下来我们尝试对变量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) 
}

现在编译器就不会再报错了,重新运行一下代码

在这里插入图片描述

可以看到,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也允许我们自
由地定义函数,语法规则如下:

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) 
}

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

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

现在你可以开始在LearnKotlin 文件中实现largerNumber()这个函数了,当你输入“max” 这
个单词时,Android Studio 会自动弹出如图

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

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

在这里插入图片描述

max()函数提示错误

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

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

在这里插入图片描述


http://www.niftyadmin.cn/n/5865972.html

相关文章

目标检测之FAST RCNN论文简读

前言 FAST RCNN是RCNN的改进版,针对RCNN的一些痛点进行了修改。 FAST RCNN 论文传送门 摘要 This paper proposes a Fast Region-based Convolutional Network method (Fast R-CNN) for object detection. Fast R-CNN builds on previous work to efficiently c…

【Rust中级教程】2.7. API设计原则之灵活性(flexible) Pt.3:借用 vs. 拥有、`Cow`类型、可失败和阻塞的析构函数及解决办法

喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 2.7.1. 借用(Borrowed) vs. 拥有(Owned) 针对Rust中几乎每一个函数、trait和类型&#xff…

Rust 中的内部可变性与 `RefCell<T>`

一、为什么需要内部可变性? 通常,Rust 编译器通过静态分析确保: 同一时刻只能存在一个可变引用,或任意多个不可变引用;引用始终保持有效。 这种严格的借用规则使得许多内存错误在编译阶段就能被捕获,但也…

golang性能分析之pprof

在 Go 语言中,使用 pprof 进行性能分析是优化代码的常用手段。以下简要介绍操作步骤: 1. 导入 pprof 包 在代码中导入 net/http/pprof 包(即使你不需要 HTTP 服务),它会自动注册性能分析相关的路由: impo…

steam_api.dll丢失3分钟修复指南,解决Steam游戏无法运行

你是不是刚下载好 Steam 游戏,激动双击图标,结果弹出一句 “steam_api.dll 没有被指定在 windows 上运行”?本文提供 3 种安全修复方案,详解 steam_api.dll 文件下载避坑技巧 正确存放路径,推荐一键修复工具&#xff…

体育数据系统是怎么开发的

体育数据系统的开发通常包括多个环节,涉及数据采集、处理、存储和展示等方面。下面是开发一个体育数据系统的主要步骤: 1. 需求分析与规划 确定目标:明确系统的目标,比如实时比赛数据跟踪、球员统计、比赛分析等。 确定用户群体…

CSS实现图片缺角效果

效果&#xff1a; 源码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>123</title…

力扣2382. 删除操作后的最大子段和

力扣2382. 删除操作后的最大子段和 题目 题目解析及思路 题目要求找到每次删除一个元素的最大字段和 因为删除不好做&#xff0c;可以转删除为添加&#xff0c;用并查集维护当前子段和 两部分合并(两个并查集)&#xff0c;三部分求和(两个并查集和一个元素) 代码 class S…