我有一个简单的程序来查找我的IP地址并将其转换为String。
为什么b[i]
的价值低于(int)255
?
public class FirstSocketProgramming {
public static void main (String arg[]){
InetAddress local = null;
try {
local = InetAddress.getLocalHost();
} catch (UnknownHostException e){
System.err.println
("Identity Crisis!");
System.exit(0);
}
byte[] b = local.getAddress();
System.out.println (b.toString());
System.out.println (b.length);
String strAddress="";
for (int i = 0; i < b.length; i++)
strAddress += ((int)255&b[i]) + ".";
System.out.println ("Local = " + strAddress);
}
}
答案 0 :(得分:3)
它将有符号字节转换为整数,以便获得(无符号)8位的全范围,而不是显示超过127的值的负数。
在Java中,由于字节是有符号的,因此字节的最大值为127.因此,假设数字为128.在无符号字节中,这将表示为10000000b。但是,使用2的补码负数,这变为-128。做255&amp; b [i]将值强制转换为整数(32位)并将高位置零,因此得到128而不是-128。
答案 1 :(得分:3)
地址写为一组字节,从0到255.Java将每个字节解释为 signed ,从-128到127.因此,将字节中的字符串形成为带符号的字节没有意义,例如-18.14.87.-45
。这与IP表示不匹配。
(int)255&b[i]
将b[i]
强制转换为int
,同时将其加宽,从而忽略符号并将其作为无符号读取。 (int)
是轻浮的,因为255
已被解释为宽于8位的东西。 0-255
值在下方连接。因此,您获得了类似192.168.1.200
的IP(请注意,此地址与之前给出的错误地址不匹配)。
一般来说,255&foo
(或整数n的任何2^n-1
(如65536,甚至像0xFF
这样的十六进制)是尝试安全地转换位长度。
答案 2 :(得分:3)
byte
数据类型基于Two's complement二进制有符号数表示,值范围为-128到+127。
从0到127的正值使其最高有效位等于0表示+
。
这里二进制表示与其数值相同,例如byte 00000100 = int 4
从-128到-1的负值使其最重要的位等于1代表-
但是在负范围内,二进制补码二进制表示 NOT 与其数值相同,例如,您希望byte 10000100
等于int 132
,但实际上是{{ 1}}。
简单地将-124
投射到byte
无济于事。
转换只会将1个字节扩展为4个字节,int
等于-124,而不是132,因为10000100 ==> 11111111111111111111111110000100
数据类型也基于2的补码。将int
投射到byte
是向正确方向迈出的一步,但是你还需要摆脱前面的所有这些。 int
技巧实现了这一点。
这是255&b[i]
中发生的事情:
根据{{3}} 255&b[i]
按位运算符中定义的转换规则,首先将其操作数转换为int,这意味着&
与255&b[i]
相同。当byte转换为int时,它会变宽:
((int)255)&((int)b[i])
然后执行按位AND。
10000100 = byte -124 ==> 11111111111111111111111110000100 = int -124
最终结果是11111111111111111111111110000100 = int -124
&
00000000000000000000000011111111 = int 255
--------------------------------
00000000000000000000000010000100 = int 132
答案 3 :(得分:0)
ip地址是合乎逻辑的,并且使用subnet_mask来查找net_id和host_id。在示例中它是相同的但非常不寻常。 subnet_mask可用于创建许多net_id。请阅读此处的示例:http://www.garykessler.net/library/subnet_masks.html。