App 更新檢查時,版本號比對是核心邏輯。直接使用 String.compareTo() 會導致嚴重錯誤:例如 "9.9.9" 被判定大於 "10.0.1"。本文提供一個健壯的版本號比較工具方法,支援任意段數、前導零、非數字字元防禦。
String.compareTo() 採字典序逐字元比較,'9' > '1' 導致 "9.9.9" > "10.0.1",違背語意版本排序規則。
. 分割版本字串為段陣列。public class VersionUtils {
/**
* 比較兩個版本號
* @return 1: v1 > v2, 0: 相等, -1: v1 < v2
*/
public static int compareVersion(String v1, String v2) {
if (v1 == null || v2 == null) throw new IllegalArgumentException("版本號不可為 null");
if (v1.equals(v2)) return 0;
String[] seg1 = v1.split("\\.");
String[] seg2 = v2.split("\\.");
int len = Math.max(seg1.length, seg2.length);
for (int i = 0; i < len; i++) {
int n1 = i < seg1.length ? parseSegment(seg1[i]) : 0;
int n2 = i < seg2.length ? parseSegment(seg2[i]) : 0;
if (n1 != n2) return n1 > n2 ? 1 : -1;
}
return 0;
}
private static int parseSegment(String seg) {
try {
// 過濾非數字字元,防止 "1.0.0-beta" 等格式拋出異常
return Integer.parseInt(seg.replaceAll("\\D", ""));
} catch (NumberFormatException e) {
return 0;
}
}
// 測試
public static void main(String[] args) {
System.out.println(compareVersion("9.9.9", "10.0.1")); // -1
System.out.println(compareVersion("1.0.0", "1.0.0")); // 0
System.out.println(compareVersion("2.5.12", "2.5.3")); // 1
System.out.println(compareVersion("1.01", "1.001")); // 0 (前導零無影響)
System.out.println(compareVersion("1.0.0-alpha", "1.0.0")); // 0 (非數字被忽略)
}
}
若需完整支援 SemVer(如 1.0.0-alpha.1、1.0.0+build.123),建議引入成熟庫:
org.apache.maven:maven-artifact 的 DefaultArtifactVersion 或 ComparableVersion。androidx.versionedparcelable:versionedparcelable 內建工具或自行實作 SemVer 解析器。Major.Minor.Patch 三段式純數字,避免解析歧義。掌握正確的版本號比較邏輯,是保障 App 更新流程可靠性的關鍵一環。