Guava - InetAddress.coerceToInteger返回int而不是long

5

我有一个关于Guava的InetAddress.coerceToInteger方法的问题。

根据文档,该方法为:

public static int coerceToInteger(InetAddress ip)

“返回表示IPv4地址的整数,而不管提供的参数是否为IPv4地址。”

但是,IPv4范围是无符号32位,而Java的int是有符号的 - 这意味着返回值只能覆盖IPv4相关范围的一半。

我是否错过了什么,还是该方法存在真正的问题?

谢谢

3个回答

8

一个32位的值就是一个32位的值,无论它是带符号还是无符号,它都可以有2^32个取值。如果你有一个像192.168.0.1这样的地址,它会成为一个负数,但没有信息丢失。如果你将它转换成字节(也带符号),也不会损失任何信息。

顺便说一句:对于IPv4地址,你可以使用这个技巧。

int address = ip.hashCode();

要将一个32位的有符号数值视为32位的无符号数值,您可以:
int address32 = ...
long address = address32 & 0xFFFFFFFFL;

然而,在大多数情况下,您不需要这样做。

谢谢Peter。我明白了。我想我会在我的Java代码中将它用作int,在插入到数据库之前(作为无符号int)我会使用你的十六进制值技巧。但是我不理解你关于IPv4的hashCode的观点。你能否扩展一下你的解释? - Ido
这个数据结构内部将地址存储为int,当你请求hashCode()时,它恰好会返回这个值。我更喜欢有一个类似getAddress()的方法来获取该值,但在这种情况下它也可以正常工作。 - Peter Lawrey
1
好的,在InetAddress类中理解了hashCode的作用。但正如这里所说,这并不是一定保证的。 - Ido
因此,一个能够保证执行相同操作的方法会更好。 - Peter Lawrey

2
我认为Javadoc已经包含了答案:
IPv6地址在转换为整数之前被强制转换为IPv4地址。
只要有应用程序假定所有IP地址都是IPv4地址,并且因此可以安全地转换为整数(无论出于什么目的),就可以使用此函数处理IPv6地址,直到应用程序得到适当修复。
注意:将IPv6地址强制转换为IPv4地址只能用于基本标识或索引到真实InetAddresses集合中。它们不能用作网络通信目的的真实地址。
换句话说,如果您提供一个IPv6地址,请不要期望它是一个实际可用的地址。在您的代码或网络中,准备好处理带有特殊条件的强制转换地址。在我看来,文档可以从示例中获得很大的收益。

1
在Java中,long是一个64位值,而IPv4地址只是一个32位值。挑战在于,Java没有无符号数据类型,因此需要一些技巧才能读取无符号值,通常通过上转换为long来实现。Guava也可以解决这个问题:
InetAddress addr = InetAddress.getLocalHost();
long ip = UnsignedInts.toLong (InetAddresses.coerceToInteger (addr));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接