Kotlin入门等式判断的情况

话说等式可是编程语言最基本的表达式之一,不管哪种高级语言,无一例外都采用双等号“==”判断两个变量是否相等;就算是复杂的对象,在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) {

tv_check_title.text = "比较 date1 和 date2 是否结构相等"

//结构相等比较的是二者的值

val result = date1 == date2

tv_check_result.text = "==的比较结果是$result"

}

tv_check_title.text = "比较 date1 和 date2 是否结构不等"

//结构不等比较的是二者的值

val result = date1 != date2

tv_check_result.text = "!=的比较结果是$result"

}

tv_check_title.text = "比较 date1 和 date2 是否引用相等"

//引用相等比较的是二者是不是同一个东西,即使克隆的一模一样也不是一个东西

val result = date1 === date2

tv_check_result.text = "===的比较结果是$result"

}

tv_check_title.text = "比较 date1 和 date2 是否引用不等"

//引用相等倒过来便是引用不等

val result = date1 !== date2

tv_check_result.text = "!==的比较结果是$result"

}

}

}

上述代码的date2从date1克隆而来,所以二者的值是完全一样的,区别仅仅是存储的地址不同。接着使用双等号“==”以及“!=”进行结构判断,运算结果为相等,详细结果如下图所示。

继续使用三等号“===”以及“!==”进行引用判断,运算结果却是不等,详细结果如下图所示。

以上的实验结果,证明了引用相等校验的是变量的唯一性,而结构相等校验的是变量的等值性。

is和in

除了判断两个变量是否相等,还有其它维度的等式判断,例如校验变量是否为某种类型、校验数组中是否存在某个元素等等,对于这些特殊的等式判断,还得具体问题具体分析。

譬如说校验变量是否为某种类型,按照Java的写法自然采用instanof,具体判断语句形如“变量名称 instanof 类型名称”;如果校验变量是否非某种类型,则需在instanof外层再加上“!”这个非运算符,具体语句形如“!(变量名称 instanof 类型名称)”。由此可见,Java的类型判断方式不是太精简,尤其是非的表达式有点啰嗦。

在Kotlin中,若要校验变量是否为某种类型,使用的关键字是in,具体写法形如“变量名称 in 类型名称”;若要校验变量是否非某种类型,使用的关键字是!in,具体写法形如“变量名称 !in 类型名称”。与Java相比,Kotlin的类型判断足够精炼,表达起来也更加方便。下面来看看Kotlin判断变量类型的一个代码例子:

val oneLong:Long = 1L

btn_equal_type.setOnClickListener {

if (isEqual) {

tv_check_title.text = "比较 oneLong 是否为长整型"

//is用于判断是否等于某类型,对应的Java关键字是instanof

val result = oneLong is Long

tv_check_result.text = "is的比较结果是$result"

} else {

tv_check_title.text = "比较 oneLong 是否非长整型"

//!is用于判断是否不等于某类型

val result = oneLong !is Long

tv_check_result.text = "!is的比较结果是$result"

}

isEqual = !isEqual

}

这个例子校验了变量oneLong是否为Long长整型数。

另一种特殊的等式判断,是校验数组中是否存在某个元素。倘若由Java来实现,并没有现成的可用运算符,只能循环遍历该数组,逐个进行数组元素的等式判断,无疑是大费周章。现在有了Kotlin,则可直接使用关键字in来校验,通过“变量名 in 数组名”即可判断数组是否存在等值元素,通过“变量名 !in 数组名”即可判断数组是否不存在等值元素。

照例来个数组判断代码,观察一下Kotlin如何实现数组内部的等式判断,具体的处理代码如下所示:

val oneArray:IntArray = intArrayOf(1, 2, 3, 4, 5)

val four:Int = 4

val nine:Int = 9

btn_equal_item.setOnClickListener {

when (count++%4) {

tv_check_title.text = "比较 $four 是否存在数组oneArray中"

//in用于判断变量是否位于数组或容器中,Java判断数组中是否存在某元素只能采取循环遍历的方式

val result = four in oneArray

tv_check_result.text = "in的比较结果是$result"

}

tv_check_title.text = "比较 $four 是否不在数组oneArray中"

//!in用于判断变量是否不在数组或容器中

val result = four !in oneArray

tv_check_result.text = "!in的比较结果是$result"

}

tv_check_title.text = "比较 $nine 是否存在数组oneArray中"

//in用于判断变量是否位于数组或容器中

val result = nine in oneArray

tv_check_result.text = "in的比较结果是$result"

}

tv_check_title.text = "比较 $nine 是否不在数组oneArray中"

//!in用于判断变量是否不在数组或容器中

val result = nine !in oneArray

tv_check_result.text = "!in的比较结果是$result"

}

}

}

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181120G0DCHT00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券