IPv4 地址本質是 32 位無符號整數。Java 無無符號類型,但可用 long 或位運算配合 int 完成互轉。本文提供生產級 IPv4Util:IP↔int、IP↔byte[]、CIDR 範圍解析、掩碼範圍計算,含單元測試主方法。
// IP → int (大端序 / 網絡字節序)
int ipToInt(String ip) {
String[] parts = ip.split("\\.");
return (Integer.parseInt(parts[0]) << 24) |
(Integer.parseInt(parts[1]) << 16) |
(Integer.parseInt(parts[2]) << 8) |
(Integer.parseInt(parts[3]));
}
// int → IP
String intToIp(int ipInt) {
return ((ipInt >>> 24) & 0xFF) + "." +
((ipInt >>> 16) & 0xFF) + "." +
((ipInt >>> 8) & 0xFF) + "." +
(ipInt & 0xFF);
}
關鍵:使用無符號右移 >>>> 確保高位補 0,& 0xFF 取低 8 位。
public final class IPv4Util {
private static final int INADDRSZ = 4;
// IP → byte[] (借助 InetAddress 校驗合法性)
public static byte[] ipToBytes(String ip) {
try { return InetAddress.getByName(ip).getAddress(); }
catch (Exception e) { throw new IllegalArgumentException("Invalid IP: " + ip); }
}
// byte[] → IP 字符串
public static String bytesToIp(byte[] b) {
return (b[0]&0xFF)+"."+(b[1]&0xFF)+"."+(b[2]&0xFF)+"."+(b[3]&0xFF);
}
// byte[] → int
public static int bytesToInt(byte[] b) {
return ((b[3]&0xFF) ) |
((b[2]&0xFF) << 8 ) |
((b[1]&0xFF) << 16 ) |
((b[0]&0xFF) << 24 );
}
// int → byte[]
public static byte[] intToBytes(int ipInt) {
return new byte[] {
(byte)((ipInt >>> 24) & 0xFF),
(byte)((ipInt >>> 16) & 0xFF),
(byte)((ipInt >>> 8) & 0xFF),
(byte)(ipInt & 0xFF)
};
}
// CIDR 解析 "192.168.1.0/24" → [networkInt, broadcastInt]
public static int[] parseCidr(String cidr) {
String[] parts = cidr.split("/");
int ipInt = ipToInt(parts[0]);
int prefix = Integer.parseInt(parts[1]);
if (prefix < 0 || prefix > 31) throw new IllegalArgumentException("Invalid prefix");
int mask = (prefix == 0) ? 0 : (0xFFFFFFFF << (32 - prefix));
int network = ipInt & mask;
int broadcast = network | (~mask);
return new int[]{network, broadcast};
}
// 掩碼形式 "192.168.1.1/255.255.255.0" → 範圍
public static int[] parseMask(String ip, String mask) {
int ipInt = ipToInt(ip);
int maskInt = ipToInt(mask);
int network = ipInt & maskInt;
int broadcast = network | (~maskInt);
return new int[]{network, broadcast};
}
}
IP: 192.168.8.1 -> int: -1062729471
int: -1062729471 -> IP: 192.168.8.1
192.168.1.1/24 -> int範圍: [-1062731775, -1062729728]
192.168.1.1/24 -> IP範圍: [192.168.1.0, 192.168.1.255]
192.168.1.1, 255.255.255.0 -> int範圍: [-1062731775, -1062729728]
192.168.1.1, 255.255.255.0 -> IP範圍: [192.168.1.0, 192.168.1.255]
注意:Java int 有符號,192.168.x.x 高位為 1 顯示為負數,**不影響位運算邏輯**,僅顯示不同。存儲數據庫建議用 BIGINT UNSIGNED 或存字符串。
Set 存儲 ipToLong(),O(1) 判斷。ipInt >= network && ipInt <= broadcast。long start, end, geoId 區間樹/B+樹查詢。掌握 >>>>、& 0xFF、<< 位運算組合,即可在 Java 中高效實現 IPv4 與整數雙向轉換。IPv4Util 封裝了校驗、CIDR/掩碼雙模式範圍解析、字節數組中轉,可直接納入項目公共庫。