『软件工程』计算机界 TOP 3 难题:“相等”是软件工程中许多重大问题的根源( 六 )


注意这与JavaScript的行为不同 。 JavaScript也有与PHP类似的(但并不是一样的!)==和===运算符;但JavaScript会认为两侧都为字符串 , 然后返回比较结果false 。
幸运的是 , PHP提供了===(“全等”)运算符 , 在这种情况下能给出正确结果 。 我想说永远不要使用== , 但==会在对象上执行结构比较 , 有时候正是你需要的!因此我只能说 , 使用==时要格外小心 , 因为它不能在基础类型上正确工作 。
『软件工程』计算机界 TOP 3 难题:“相等”是软件工程中许多重大问题的根源
本文插图
常见错误:相等不是对称的
如果你要在Java中重载.equals , 那么你必须负责确保相等的定律成立!
如果不加注意 , 那么很容易就会导致不对称的相等 , 即a.equals(b) != b.equals(a) 。
即使不考虑的情况(因为会导致PointerException , 而.equals()是允许这种情况发生的:https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-) , 如果你继承一个类并重载.equals , 也最好多加小心!
@Overridepublic boolean equals(Object o) { if (this == o) return true; if (o == ) return false; if (!o.getClass.isAssignableFrom(getClass)) // 危险!这一步是错的! return false; ThisClass thisClass = (ThisClass) o; // 字段比较 // ...} 【『软件工程』计算机界 TOP 3 难题:“相等”是软件工程中许多重大问题的根源】如果ThisClass和ASubtypeOfThisClass都用类似上面的代码重载了.equals , 那么a.equals(b)就可能不等于b.equals(a)!正确的比较应该是:
if (getClass != o.getClass) return false; 这不仅仅是我的个人看法 , 也是Object.equals的契约的要求(https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-) 。
『软件工程』计算机界 TOP 3 难题:“相等”是软件工程中许多重大问题的根源
本文插图
常见错误:相等没有传递性
回忆一下相等比较的定律之一就是应当具有传递性 , 即如果a = b 且 b = c , 那么 a = c 。 不幸的是 , 与类型转换(type coersion)放在一起后 , 许多语言都会在这里出问题 。
在JavaScript中 ,
'' == 0; // true0 == '0'; // true'' == '0'; // false! 因此在JavaScript中永远不要使用== , 应该使用=== 。
『软件工程』计算机界 TOP 3 难题:“相等”是软件工程中许多重大问题的根源
本文插图
常见错误:相等性不一致
在Kotlin中 , ==会根据变量类型返回不同的值 , 即使对于同一个变量:
fun equalsFloat(a: Float, b: Float) { println(a == b);}fun equalsAny(a: Any, b: Any) { println(a == b);}fun main(args: Array) { val a = Float.NaN; val b = Float.NaN; equalsFloat(a, b); equalsAny(a, b);}// prints false, true 这是一个非常不幸的语言特性组合 , 可能会导致违反直觉的行为 。
『软件工程』计算机界 TOP 3 难题:“相等”是软件工程中许多重大问题的根源
本文插图
常见错误:在应当使用结构相等的地方使用引用相等


推荐阅读