Java 0xffffffff隐式类型转换的坑
一、场景复现
项目需求,long的低32位存储ip地址,需要将ip信息展示成为字符串ip。
public static void main(String[] args){
long ipLong = 0x457145130A1901F6L;
String ip = longToIp(ipLong&0xffffffff);//取低32位
System.out.println(ipLong);
System.out.println(ip);
}
public static String longToIp(long longIP){
StringBuffer sb=new StringBuffer("");
//直接右移24位
sb.append(String.valueOf(longIP>>>24));
sb.append(".");
//将高8位置0,然后右移16位
sb.append(String.valueOf((longIP&0x00FFFFFF)>>>16));
sb.append(".");
sb.append(String.valueOf((longIP&0x0000FFFF)>>>8));
sb.append(".");
sb.append(String.valueOf(longIP&0x000000FF));
return sb.toString();
}
输出:
5003856609061437942
298253095690.25.1.246
二、分析原因
因为long&int最终会将int类型隐式转换成long类型,而0xffffffff的值为-1(java是使用补码存储数值的),在隐式类型转换过程中扩展为long类型-1(0xffffffffffffffff),并不是0x00000000ffffffff。
所以需要将0xffffffff写为0xffffffffL(long类型),这样才能避免隐式转换带来错误的结果。
public static void main(String[] args){
long ipLong = 0x457145130A1901F6L;
String ip = longToIp(ipLong&0xffffffffL);//取低32位,L表示long类型
System.out.println(ipLong);
System.out.println(ip);
}
public static String longToIp(long longIP){
StringBuffer sb=new StringBuffer("");
//直接右移24位
sb.append(String.valueOf(longIP>>>24));
sb.append(".");
//将高8位置0,然后右移16位
sb.append(String.valueOf((longIP&0x00FFFFFF)>>>16));
sb.append(".");
sb.append(String.valueOf((longIP&0x0000FFFF)>>>8));
sb.append(".");
sb.append(String.valueOf(longIP&0x000000FF));
return sb.toString();
}
输出:
5003856609061437942
10.25.1.246
补充:整数默认int类型,在big&small表达式中,small为(byte)0xff、(short)0xffff、(int)0xffffffff 的-1隐式转换都会出现此类问题