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

以下代码可以获取到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,也不会溢出。

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值