Kotlin入门(17)等式判断的情况
话说等式可是编程语言最基本的表达式之一,不管哪种高级语言,无一例外都采用双等号“==”判断两个变量是否相等;就算是复杂的对象,在Java中也可通过equals函数判断两个实例是否相等。按理说这些能够满足绝大多数场合的要求了,那么Kotlin又给等式判断加入了哪些新概念呢?下面就让我们好好探讨一下具体业务中的等式判断。
结构相等
基本数据类型如整型、长整型、浮点数、双精度数、布尔型,无论是在C/C++还是在Java抑或是在Kotlin,都使用双等号“==”进行两个变量的相等性判断。至于字符串类型,则比较特殊,因为最早C语言是在内存中开辟一块区域,利用这块区域存储字符串,并返回一个字符指针指向该区域的首地址,此时如果对两个字符指针进行“==”运算,结果是比较两个指针指向的地址是否相等,而非比较两个地址存储的字符串是否相等;所以C语言判断两个字符串是否相等,用到的是strcmp函数;Java参考了C++,虽然不再使用字符指针,而使用String类型表示字符串,但是Java判断两个字符串是否相等,采用了equals函数,从一个函数换成另一个函数,仍然是换汤不换药,没有本质上的改变。
现在Kotlin痛定思痛,决心要革除这种沿袭已久的积弊,反正都把字符串当作跟整型一样的基本数据类型了,何不直接统一相关的运算操作符?因此,既然整型变量之间使用双等号“==”进行等式判断,字符串变量之间也能使用双等号“==”来判断;以此类推,判断两个字符串是否不相等,通过不等运算符“!=”即可直接辨别。从Java到Kotlin,改变后的等式判断表达式如下表所示:
判断两个字符串是否相等 strA.equals(strB) -> strA == strB
判断两个字符串是否不等 !strA.equals(strB) -> strA != strB
下面是个Kotlin判断字符串相等性的代码例子:
val helloHe:String = "你好"
val helloShe:String = "妳好"
btn_equal_struct.setOnClickListener {
if (isEqual) {
tv_check_title.text = "比较 $helloHe 和 $helloShe 是否相等"
//比较两个字符串是否相等的Java写法是 helloHe.equals(helloShe)
val result = helloHe == helloShe
tv_check_result.text = "==的比较结果是$result"
} else {
tv_check_title.text = "比较 $helloHe 和 $helloShe 是否不等"
//比较两个字符串是否不等的Java写法是 !helloHe.equals(helloShe)
val result = helloHe != helloShe
tv_check_result.text = "!=的比较结果是$result"
}
isEqual = !isEqual
}
其中“==”的判断结果如下面左图所示,“!=”的判断结果如下面右图所示。
推而广之,不单单字符串String类型,凡是Java中实现了equals函数的类,其对象实例均可在Kotlin中使用“==”和“!=”进行等式判断。这种不比较存储地址,而是比较变量结构内部值的行为,Kotlin称之为结构相等,意即模样相等,通俗地说就是一模一样。
引用相等
有时候仅仅判断两个变量值是否相等,并不足以完成某种一致性判断,现实生活中还有更严格的真伪鉴定需求,比如真假美猴王、文物的真品与赝品、兰亭集序的真迹与摹本等等。倘若按照结构相等的判断标准,复制品和真品在外观上没有区别,毫无疑问就是相等的。但这个相等的结果明显与大众的认知相悖,因为真品是唯一的,复制品再怎么逼真也不可能与真品等价,所以结构相等并不适用于真伪鉴定,如何判断真伪需要另一种由内而外全部相等的判断准则,该准则叫做引用相等,意思是除了值相等以外,还要求引用的地址(即存储地址)也必须相等。
在Kotlin中,结构相等的运算符是双等号“==”,那么引用相等的运算符便是三个等号“===”,多出来的一个等号表示连地址都要相等;结构不等的运算符是“!=”,相对应的,引用不等的运算符是“!==”。不过在大多数场合,结构相等和引用相等的判断结果是一致的,下面列出常见的几种等式判断情景:
1、对于基本数据类型,包括整型、浮点数、布尔型、字符串,结构相等和引用相等没有区别;
2、同一个类声明的不同实例,如果不是每个属性都相等,则其既是结构相等,又是引用相等;
3、同一个类声明的不同实例,如果equals校验的每个属性都相等(譬如通过clone方法克隆而来),则其结构相等,但引用不等;
为详细说明以上的等式判断,下面给出具体的代码例子,利用系统自带的时间Date类演示一下结构相等和引用相等的区别:
val date1:Date = Date()
val date2:Any = date1.clone() //从date1原样克隆一份到date2
btn_equal_refer.setOnClickListener {
when (count++%4) {
0 -> {
tv_check_title.text = "比较 date1 和 date2 是否结构相等"
//结构相等比较的是二者的值
val result = date1 == date2
tv_check_result.text = "==的比较结果是$result"
}
1 -> {
tv_check_title.text = "比较 date1 和 date2 是否结构不等"
//结构不等比较的是二者的值
val result = date1 != date2
tv_check_result.text = "!=的比较结果是$result"
}
2 -> {
tv_check_title.text = "比较 date1 和 date2 是否引用相等"
//引用相等比较的是二者是不是同一个东西,即使克隆的一模一样也不是一个东西
val result = date1 === date2
tv_check_result.text = "===的比较结果是$result"
}
else -> {
tv_check_title.text = "比较 date1 和 date2 是否引用不等"
//引用相等倒过来便是引用不等
val result = date1 !== date2
tv_check_result.text = "!==的比较结果是$result"
}
}
}
上述代码的date2从date1克隆而来,所以二者的值是完全一样的,区别仅仅是存储的地址不同。接着使用双等号“==”以及“!=”进行结构判断,运算结果为相等,详细结果如下图所示。
继续使用三等号“===”以及“!==”进行引用判断,运算结果却是不等,详细结果如下图所示。
以上的实验结果,证明了引用相等校验的是变量的唯一性,而结构相等校验的是变量的等值性。
Kotlin入门(17)等式判断的情况的更多相关文章
- Kotlin入门教程——目录索引
Kotlin是谷歌官方认可的Android开发语言,Android Studio从3.0版本开始就内置了Kotlin,所以未来在App开发中Kotlin取代Java是大势所趋,就像当初Android ...
- 写给Android开发者的Kotlin入门
写给Android开发者的Kotlin入门 转 https://www.jianshu.com/p/bb53cba6c8f4 Google在今年的IO大会上宣布,将Android开发的官方语言更换为K ...
- Kotlin入门(28)Application单例化
Application是Android的又一大组件,在App运行过程中,有且仅有一个Application对象贯穿应用的整个生命周期,所以适合在Application中保存应用运行时的全局变量.而开展 ...
- Kotlin入门(9)函数的基本用法
上一篇文章介绍了Kotlin新增的空安全机制,控制语句部分可算是讲完了,接下来将连续描述Kotlin如何定义和调用函数,本篇文章先介绍函数的基本用法. 前面几篇文章介绍控制语句之时,在setOnCli ...
- Kotlin入门(11)江湖绝技之特殊函数
上一篇文章介绍了Kotlin对函数的输入参数所做的增强之处,其实函数这块Kotlin还有好些重大改进,集中体现在几类特殊函数,比如泛型函数.内联函数.扩展函数.尾递归函数.高阶函数等等,因此本篇文章就 ...
- Kotlin入门(15)独门秘笈之特殊类
上一篇文章介绍了Kotlin的几种开放性修饰符,以及如何从基类派生出子类,其中提到了被abstract修饰的抽象类.除了与Java共有的抽象类,Kotlin还新增了好几种特殊类,这些特殊类分别适应不同 ...
- Kotlin入门第二课:集合操作
测试项目Github地址: KotlinForJava 前文传送: Kotlin入门第一课:从对比Java开始 初次尝试用Kotlin实现Android项目 1. 介绍 作为Kotlin入门的第二课, ...
- Kotlin入门(5)字符串及其格式化
上一篇文章介绍了数组的声明和操作,包括字符串数组的用法.注意到Kotlin的字符串类也叫String,那么String在Java和Kotlin中的用法有哪些差异呢?这便是本文所要阐述的内容了. 首先要 ...
- Kotlin入门(13)类成员的众生相
上一篇文章介绍了类的简单定义及其构造方式,当时为了方便观察演示结果,在示例代码的构造函数中直接调用toast提示方法,但实际开发是不能这么干的.合理的做法是外部访问类的成员属性或者成员方法,从而获得处 ...
随机推荐
- Spring webFlux:坐等spring-boot-starter-data-mysql-reactive
spring-boot-starter-data-mongodb-reactive spring-boot-starter-data-redis-reactive 坐等 spring-boot-sta ...
- 第三篇: 服务消费者(Feign)
本文根据https://blog.csdn.net/forezp/article/details/81040965写出,修正了部分瑕疵,在此对那位博主表示感谢. 上一篇文章讲述通过RestTempla ...
- 数据库之SqlDataAdapter
SqlDataAdapter 类 表示用于填充 DataSet 和更新 SQL Server 数据库的一组数据命令和一个数据库连接.无法继承此类. 命名空间:System.Data.SqlClient ...
- 【BJOI2019】排兵布阵 DP
题目大意:有$n$座城堡,$s$轮游戏. 对于第$x$轮,第i座城堡的士兵数量为$a[x][i]$. 如果你需要攻下第i座城堡,你在第i座城堡部署的士兵必须严格大于$2a[x][i]$,如果攻下了你会 ...
- python常用函数和方法 - 备忘
语法语句篇 除法运算(精确运算和截断运算) 在python2中,除法运算通常是截断除法.什么是截断除法: >>> 3/4 0 # 自动忽略小数项 要是想 得到正确结果 怎么办呢? m ...
- Zabbix系列之三——部署JMX监控tomcat
zabbix提供了一个java gateway的应用去监控jmx(Java Management Extensions,即Java管理扩展)是一个为应用程序.设备.系统等植入管理功能的框架.JMX可以 ...
- Android 性能优化-启动时间
adb shell am start -W -n com.xxxx(包名)/xxx.xxxActivity(launch Activity)
- AWS EC2实例Ubuntu系统设置root用户密码并使用root/ubuntu用户登录
参考链接:http://www.wangchao.info/1137.html 注意:链接中写的简化了,其中重启服务的命令似乎不太适用,可能是不通用,我下面描述的方式亲测可行,如有其他疑问请留言: ...
- Java NIO中的缓冲区Buffer(一)缓冲区基础
什么是缓冲区(Buffer) 定义 简单地说就是一块存储区域,哈哈哈,可能太简单了,或者可以换种说法,从代码的角度来讲(可以查看JDK中Buffer.ByteBuffer.DoubleBuffer等的 ...
- iOS开发(3):tips提示 | 如何提示一行文字或一个图片
我有一个需求:在点击或长按某个按钮时,显示提示,包括简单的文字提示,还有复杂一点的图片甚至是动态图的提示(可能还要加上文字),怎么实现呢? (1)文字tips 使用之前介绍的qmuikit里面的QMU ...