Kotlin 中的等号(’==’、’===’ 和 ‘equals’)

我们经常需要在 Kotlin 中比较两个变量或对象的数据或者两个对象的引用。这带来了另一个问题,在这种情况下我们应该使用哪种相等检查。让我们弄清楚 Kotlin 中可用的检查类型有哪些。

结构相等(’==’)。

==运算符用于比较两个变量的数据。
在Kotlin中,==操作符只用于比较数据或变量,而在Java或其他语言中,==一般用于比较引用。
在Kotlin中,与==相对应的负数是!=,用于比较两个值是否相互不相等。

引用相等(’===’)

=== 操作符用于比较两个变量或对象的引用。
只有当两个对象或变量都指向同一个对象时,它才是真的。
在Kotlin中,===的否定对应项是!===,用于比较两个值是否相互不相等。
对于在运行时表示为原始类型的值(例如Int),===平等性检查等同于===检查。

.equals 方法

.equals(other: Any?)方法在Any类中实现,可以在任何扩展类中重载。
.equals方法也像==运算符一样比较变量或对象的内容,但在浮点数和双倍数的比较中,它的行为有所不同。
==和.equals的区别在于,在浮点数和双倍数的比较中,.equals与IEEE 754浮点运算标准不一致。

不同意 IEEE 754 浮点算术标准是什么意思?

它的意思是,

    <ul>
            <li><mark>NaN</mark> is considered equal to itself</li>
            <li><mark>NaN</mark> is considered greater than any other element including POSITIVE_INFINITY</li>
            <li><mark>-0.0</mark> is considered less than <mark>0.0</mark></li>
    </ul>

迷茫?

将通过示例解释这一点以及所有内容。
首先,让我们通过所有相等检查来比较两个原始类型 Int 变量。

  
val int1 = 10
val int2 = 10

println(int1 == int2) // true
println(int1.equals(int2)) // true
println(int1 === int2) // true

上述所有的比较都将打印为真,因为原始数据类型只在===的情况下检查值,而在我们的例子中,这将是相等的。

现在让我们使用包装类来代替原始数据类型,并比较所有三个相等的检查。

  
val first = Integer(10)
val second = Integer(10)

println(first == second) //true
println(first.equals(second)) //true
println(first === second) //false

在上面的例子中,==和.equals打印为真,因为它们只比较数值,而==则是比较对象的引用,这些对象是不同的,所以它打印为假。

现在,让我们考虑另一种情况,我们创建了自己的自定义类对象,并与所有三个检查进行比较。

  
class Employee (val name: String)
val emp1 = Employee(“Suneet”)
val emp2 = Employee(“Suneet”)

println(emp1 == emp2) //false
println(emp1.equals(emp2)) //false
println( emp1 === emp2) //false

println(emp1.name == emp2.​​name) //true
println(emp1.name.equals(emp2.​​name)) //true
println(emp1.name === emp2.​​name ) //真的

上述比较的原因是显而易见的,由于Empoyee不是原始数据类型或包装类,所有三个都是对引用进行比较,这三个检查都返回错误。但在字符串比较的情况下,如果只检查字符串的内容是相等的,那么它对每一种情况都返回真。

等等,但你说==和.equals只比较对象的内容,在我们的例子中是相等的。
正是如此。但内容比较只在数据类中起作用。
如果它是一个普通的类,即使内容相同,编译器也会认为这两个对象是不同的对象,但如果它是一个数据类,编译器会比较数据,如果内容相同则返回true。

让我们把上面的类改为数据类。

  
data class Employee (val name: String)
val emp1 = Employee("Suneet")
val emp2 = Employee("Suneet")

println(emp1 == emp2)         //true
println(emp1.equals(emp2))    //true
println(emp1 === emp2)        //false

println(emp1.name == emp2.name)      //true
println(emp1.name.equals(emp2.name)) //true
println(emp1.name === emp2.name)     //true

最后一件事,让我们将浮点值与负零和正零进行比较。

  
val negZero = -0.0f
val posZero = 0.0f

println(negZero == posZero) //true
println(negZero.equals(posZero)) //false
println(negZero === posZero) //true

如同Float和Double的比较,.equals不符合IEEE 754浮点运算标准,当-0.0与0.0比较时,它返回错误,而==和==则返回真实。

要记住的几件事,

1.由于Kotlin中没有像String(“”)那样的构造函数,如果内容相等,所有的字符串比较都会得到true。
2.当明确地与null比较时,没有必要优化代码。一个==null将被自动翻译成一个==null,因为null是一个引用,在最后,它将是一个引用检查。