Android 開發中使用 UUID 做藍牙/設備唯一標識時,明明 Log 打印內容相同,== 比較卻返回 false,.equals() 甚至也可能失效。本文揭示根因並給出正確比較姿勢。
// 從 Intent/SharedPreferences/藍牙掃描獲取
UUID uuid1 = ...; // 來源 A
UUID uuid2 = ...; // 來源 B
Log.d("TAG", "uuid1: " + uuid1); // 輸出: 00001101-0000-1000-8000-00805F9B34FB
Log.d("TAG", "uuid2: " + uuid2); // 輸出: 00001101-0000-1000-8000-00805F9B34FB
if (uuid1 == uuid2) { ... } // ❌ false - 比較對象引用
if (uuid1.equals(uuid2)) { ... } // ✅ 應為 true,但某些情況仍失效?
== 比較的是對象引用(堆內存地址)UUID 是不可變類,每次 UUID.fromString()、Parcel.readSerializable()、反序列化都會創建新對象== 必然 false.equals() 應該可靠,為何仍失效?UUID.equals(Object obj) 源碼 (OpenJDK/Android):
public boolean equals(Object obj) {
if (!(obj instanceof UUID)) return false;
UUID other = (UUID) obj;
return mostSigBits == other.mostSigBits && leastSigBits == other.leastSigBits;
}
long 域 (mostSigBits, leastSigBits)
// 場景:藍牙掃描獲取的 128-bit UUID 字符串格式不標準
String str1 = "00001101-0000-1000-8000-00805F9B34FB"; // 標準 8-4-4-4-12
String str2 = "0000110100001000800000805F9B34FB"; // 無分隔符
String str3 = "1101"; // 16-bit 簡寫
UUID u1 = UUID.fromString(str1); // 正常
UUID u2 = UUID.fromString(str2); // 拋出 IllegalArgumentException!
UUID u3 = UUID.fromString(str3); // 拋出異常!
// 正確處理 16-bit 藍牙 UUID
UUID bluetoothBase = UUID.fromString("00000000-0000-1000-8000-00805F9B34FB");
long uuid16 = 0x1101;
UUID u = new UUID(bluetoothBase.getMostSignificantBits() | (uuid16 << 32),
bluetoothBase.getLeastSignificantBits());
String canonical1 = uuid1.toString().toUpperCase().replace("-", "");
String canonical2 = uuid2.toString().toUpperCase().replace("-", "");
if (canonical1.equals(canonical2)) { ... }
if (uuid1.getMostSignificantBits() == uuid2.getMostSignificantBits() &&
uuid1.getLeastSignificantBits() == uuid2.getLeastSignificantBits()) { ... }
public final class UuidUtils {
public static boolean equals(UUID a, UUID b) {
if (a == b) return true;
if (a == null || b == null) return false;
return a.getMostSignificantBits() == b.getMostSignificantBits() &&
a.getLeastSignificantBits() == b.getLeastSignificantBits();
}
public static UUID fromBluetooth16Bit(int uuid16) {
UUID base = UUID.fromString("00000000-0000-1000-8000-00805F9B34FB");
return new UUID(base.getMostSignificantBits() | ((long)uuid16 << 32),
base.getLeastSignificantBits());
}
public static String toCanonicalString(UUID uuid) {
return uuid.toString().toUpperCase().replace("-", "");
}
}
mostSigBits、leastSigBits 十六進制:Log.d("TAG", String.format("%016X%016X", uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()));Objects.equals(uuid1, uuid2) 防空指針核心原則:永不使用 == 比較 UUID,統一規範字符串解析格式,封裝工具類項目級複用。