[英]Prove that A == B, B==C, A != C
是否存在傳遞定律不成立的對象或原始類型? 例如
A == B, B == C 但 A != B
我不是在談論 equals() 方法。 我對 == 操作感興趣
我們能證明這一點嗎?
干得好。 A==B
和B==C
導致Float
被提升為浮點數,所以==
返回 true。 但是, A==C
是引用相等,這是錯誤的。
Float A = new Float(1.0f);
float B = 1.0f;
Float C = new Float(1.0f);
System.out.println(A==B);
System.out.println(B==C);
System.out.println(A==C);
Float
在這里並不特殊,它可以很容易地是Integer
或Boolean
。
以下是語言規范中的相關部分:
15.21.1. 數值相等運算符 == 和 !=
如果相等運算符的操作數都是數字類型,或者一個是數字類型而另一個可轉換(第 5.1.8 節)為數字類型,則對操作數執行二進制數字提升(第 5.6.2 節)。
和
15.21.3. 引用相等運算符 == 和 !=
如果相等運算符的操作數都是引用類型或空類型,則該操作是對象相等。
這是第二個反例,這次使用的事實是,比較long
和float
是使用float
比較完成的。
long a = 99999999999999L;
float b = 99999999999999.0f;
long c = 99999999999998L;
System.out.println(a==b);
System.out.println(b==c);
System.out.println(a==c);
第三,我認為即使 A、B 和 C 是同一類型,理論上也可能存在非傳遞性。
如果 A 和 C 是雙擴展指數值(與它們最近的雙精度值 B 相同),那么當計算 A==B 和 B==C 時,語言實現可能會選擇舍入 A 和 C到最接近的雙精度值(即 B)。 當執行A == C中,它也可以同樣不會選擇圓。 必須在未標記為 FP-strict 的上下文中進行比較
本質上,“5.1.13. 值集轉換”為 Java 提供了一組有限的實現定義的非 FP 嚴格浮點/雙精度計算行為,並且可以(至少在理論上)利用這一點來找到相等的反例傳遞性。
Swift 提供了一個非常奇怪的例子。 在這里,不是引用語義在起作用,而是嵌套可選項被包裝的程度,以及編譯器顯式解開該可選項的程度,開始發揮作用:
let a = nil as Int? as Int?? as? Int?
let b = nil as Int? as Int??
let c: Int? = nil
assert(b == a) // passes
assert(c == a && c == nil && a != nil) // passes. wtf
assert(c == b && u == nil && b != nil) // passes. wtf
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.