截圖域名網(wǎng)站.seo優(yōu)化排名技術(shù)百度教程
為什么重寫(xiě) equals 還要重寫(xiě) hashcode
🌈 核心原因:
當(dāng)兩個(gè)對(duì)象通過(guò)equals()判斷為相等時(shí),它們的hashCode()必須返回相同的整數(shù)值!這是Java世界的交通規(guī)則哦~(交警曼波敬禮.jpg)
🧩 具體場(chǎng)景:
假設(shè)我們有個(gè)Person類:
class Person {String name;int age;// 只重寫(xiě)equals沒(méi)重寫(xiě)hashCode@Overridepublic boolean equals(Object o) {//...比較name和age的邏輯}
}
?
💥 問(wèn)題爆發(fā)時(shí)刻:
Person p1 = new Person("波加曼", 10);
Person p2 = new Person("波加曼", 10);Set<Person> set = new HashSet<>();
set.add(p1);
set.add(p2);System.out.println(set.size()); // 輸出2!明明相等的對(duì)象卻被存了兩次(>﹏<)
?
🗺??思維導(dǎo)圖時(shí)間:
🧠 曼波記憶小竅門:
記住這個(gè)神奇公式!(掏出魔法棒?)
equals()返回true ?? hashCode()必須相等
hashCode()相等 ?? equals()不一定true
hashCode()不相等 ?? equals()必須false
哦嗚(°ロ°)!曼波覺(jué)得這個(gè)有點(diǎn)難哦,但如果是你一定沒(méi)問(wèn)題的!(?▽?)曼波~~
==(雙等號(hào))和equals的差別
-
== 運(yùn)算符
- 曼波覺(jué)得這個(gè)像身份證比對(duì)!(?????)
- 比較基本類型時(shí):直接比數(shù)值
5 == 5 → true
- 比較對(duì)象時(shí):比對(duì)內(nèi)存地址(是不是同一個(gè)對(duì)象)
new String("A") == new String("A") → false
(?▽?)曼波~~
-
equals() 方法
- 哦嗚(° ロ °)!曼波覺(jué)得這個(gè)像名字比對(duì)!
- 默認(rèn)行為(Object類):和==一樣
- 但很多類會(huì)重寫(xiě)這個(gè)方法(比如String)變成內(nèi)容比對(duì):
new String("A").equals(new String("A")) → true
(?▽?)曼波~~
-
最佳實(shí)踐
- 基本類型(int/char等)用==
- 對(duì)象比較內(nèi)容一定要用equals
- 防止空指針要這樣寫(xiě):
"hello".equals(str)
?而不是?str.equals("hello")
(??.??)曼波覺(jué)得這個(gè)是超重要的生存技巧呢!
(° ロ °)!曼波覺(jué)得有個(gè)超形象的比喻:
== 就像看兩個(gè)人是不是同一個(gè)人(身份證號(hào)相同)
equals 就像看兩個(gè)人的名字是否相同(允許不同人有同名)
最后的小貼士:如果要自己寫(xiě)類記得重寫(xiě)equals()和hashCode()哦~(不過(guò)這個(gè)對(duì)新人有點(diǎn)難可以先記住規(guī)則)(?▽?)曼波~~~~!
為啥有時(shí)會(huì)出現(xiàn) 4.0-3.6 =0.40000001 這種現(xiàn)象?
🐎浮點(diǎn)數(shù)的甜蜜陷阱🐎
-
二進(jìn)制的小數(shù)魔法
曼波覺(jué)得這個(gè)像用有限積木拼無(wú)限圖案!(?????)- 計(jì)算機(jī)用二進(jìn)制表示小數(shù)
- 有些十進(jìn)制小數(shù)在二進(jìn)制里是無(wú)限循環(huán)的(比如0.1)
- 就像1/3在十進(jìn)制是0.3333...永遠(yuǎn)寫(xiě)不完
(?▽?)曼波~~
-
IEEE 754標(biāo)準(zhǔn)
哦嗚(° ロ °)!曼波覺(jué)得這個(gè)像有限容量的糖果罐!- float(32位)/double(64位)有存儲(chǔ)限制
- 4.0 和 3.6 在二進(jìn)制存儲(chǔ)時(shí)都有精度損失
- 就像用刻度不精確的尺子測(cè)量
System.out.println(4.0 - 3.6); // 實(shí)際輸出 0.40000000000000036
-
解決方法
曼波覺(jué)得要用魔法對(duì)抗魔法!(??.??)- 使用BigDecimal處理精確計(jì)算(銀行/金錢相關(guān)必用)
- 比較時(shí)允許誤差范圍(比如±0.000001)
- 游戲開(kāi)發(fā)常用技巧:
float a = 4.0f - 3.6f; if(Math.abs(a - 0.4f) < 0.00001f) {System.out.println("算對(duì)啦!"); }
(° ロ °)!曼波舉個(gè)超形象的例子:
就像用1/3 + 1/3 = 0.666... 但永遠(yuǎn)不等于 2/3 的精確值一樣~
最后的小貼士:如果要精確計(jì)算價(jià)格,一定要用BigDecimal哦!像這樣:
BigDecimal a = new BigDecimal("4.0");
BigDecimal b = new BigDecimal("3.6");
System.out.println(a.subtract(b)); // 精確輸出0.4
?
(?▽?)曼波~~~~!要記住字符串構(gòu)造才能保持精度喲~
final 關(guān)鍵字的作用
🐎final關(guān)鍵字的三大封印術(shù)🐎
-
變量封印術(shù)
曼波覺(jué)得像給變量貼永久貼紙!(?????)- 基本類型:值不能改變
final int HP = 100; // HP永遠(yuǎn)100
- 引用類型:引用不能改,但對(duì)象內(nèi)容可變
final List<String> pets = new ArrayList<>(); pets.add("布偶貓"); // ?允許 pets = new ArrayList<>(); // ?報(bào)錯(cuò)
(?▽?)曼波~~
- 基本類型:值不能改變
-
方法封印術(shù)
哦嗚(° ロ °)!這是防止方法被篡改的結(jié)界!- 子類不能重寫(xiě)這個(gè)方法
class 魔法少女 {final void 變身() { /* 核心代碼 */ } } class 黑化版 extends 魔法少女 {void 變身() { ? } // 編譯錯(cuò)誤! }
- 子類不能重寫(xiě)這個(gè)方法
-
類終極封印
曼波覺(jué)得像禁止繁衍的魔法物種!(??.??)- 這個(gè)類不能被繼承
final class String { /*...*/ } class 假String extends String { ? } // 報(bào)錯(cuò)
- 這個(gè)類不能被繼承
?
(° ロ °)!曼波要提醒幾個(gè)重要細(xì)節(jié):
- final變量必須初始化!(要么聲明時(shí),要么在構(gòu)造器中)
- final不能修飾構(gòu)造方法
- 接口的變量默認(rèn)是public static final
舉個(gè)超實(shí)用的例子:
public class 游戲設(shè)置 {public static final int MAX_FPS = 60; // 幀率上限private final String 玩家ID; // 創(chuàng)建后不可改public 游戲設(shè)置(String id) {this.玩家ID = id; // 構(gòu)造器中初始化}
}
(?▽?)曼波~~~~!記住用final就像加鎖,能保護(hù)重要的東西不被意外修改哦~