您的位置:首页 > 编程语言 > Java开发

InetAddress.getByAddress(byte[] arr)源码解析

2017-05-31 22:54 567 查看
以下代码可以获取到192.168.1.3对应的主机:

InetAddress ia = InetAddress.getByAddress(new byte[] { (byte) 192,(byte) 168, 1, 3 });


参数接收的是一个byte数组,我们都知道,byte数组的范围是-128~127,那么以上代码强转成byte为什么不会溢出,还可以正确获取到对应的主机呢?

以下是getByAddress方法的源码:

public static InetAddress getByAddress(byte[] addr) throws UnknownHostException {
return getByAddress(null, addr);
}

public static InetAddress getByAddress(String host, byte[] addr) throws UnknownHostException {
return getByAddress(host, addr, -1 /* scopeId */);
}

// Do not delete. Called from native code.
private static InetAddress getByAddress(String host, byte[] addr, int scopeId) throws UnknownHostException {
if (host != null && host.length() > 0 && host.charAt(0) == '[') {
if (host.charAt(host.length()-1) == ']') {
host = host.substring(1, host.length() -1);
}
}
if (addr != null) {
if (addr.length == Inet4Address.INADDRSZ) {
//IPv4是长度为4个字节的byte数组
return new Inet4Address(host, addr);
} else if (addr.length == Inet6Address.INADDRSZ) {
//IPv6是长度为16个字节的byte数组
byte[] newAddr = IPAddressUtil.convertFromIPv4MappedAddress(addr);
if (newAddr != null) {
return new Inet4Address(host, newAddr);
} else {
return new Inet6Address(host, addr, scopeId);
}
}
}
throw new UnknownHostException("addr is of illegal length");
}


以IPv4为例,以上代码返回了:

return new Inet4Address(host, addr);


Inet4Address(String hostName, byte addr[]) {
holder().hostName = hostName;
holder().family = AF_INET;
if (addr != null) {
//看到这里就应该都明白了,底层用的是位运算,将4个字节直接按位运算转成了int类型,所以不存在溢出一说
if (addr.length == INADDRSZ) {
int address  = addr[3] & 0xFF;
address |= ((addr[2] << 8) & 0xFF00);
address |= ((addr[1] << 16) & 0xFF0000);
address |= ((addr[0] << 24) & 0xFF000000);
holder().address = address;
}
}
}


到这里我们可能还存有一个疑问,IP的最高8位也可能是11111111,那最后拼接起来的int类型IP值是不是也会溢出呢?

我们通过getHostAdress方法获取到的IP地址却是正常的:

public String getHostAddress() {
return numericToTextFormat(getAddress());
}


先看看getAdress()是怎么写的:

public byte[] getAddress() {
int address = holder().getAddress();
byte[] addr = new byte[INADDRSZ];
addr[0] = (byte) ((address >>> 24) & 0xFF);
addr[1] = (byte) ((address >>> 16) & 0xFF);
addr[2] = (byte) ((address >>> 8) & 0xFF);
addr[3] = (byte) (address & 0xFF);
return addr;
}


可以看出他是将int类型IP地址按照位运算转成了byte数组(java的API底层位运算是很常见的,提高了代码的执行效率)

static String numericToTextFormat(byte[] src) {
return (src[0] & 0xff) + "." + (src[1] & 0xff) + "." + (src[2] & 0xff) + "." + (src[3] & 0xff);
}


最终是用到了以上numericToTextFormat(byte[] src)这个静态方法,仍然是位运算,只不过这里位运算之后自动提升为了int类型,所以即便是位运算之后结果是11111111,也不会溢出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  源码 InetAddres java