1

我有一个简单的程序来查找我的 IP 地址并将其转换为字符串。为什么下面的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);  

 }  

}
4

4 回答 4

4

byte数据类型基于二进制补码二进制有符号数表示,取值范围从 -128 到 +127。

从 0 到 127 的正值的最高有效位等于 0,表示+. 这里的二进制表示与它的数值相同,例如byte 00000100 = int 4

从 -128 到 -1 的负值的最高有效位等于 1,表示- 但是在负范围内,二进制补码表示与其数值不同,例如,您希望byte 10000100等于int 132,但实际上是-124。简单地投射byteint将无济于事。

转换只是将 1 个字节扩大到 4 个字节, 10000100 ==> 11111111111111111111111110000100等于 -124,而不是 132,因为int数据类型也是基于二进制补码的。铸造是朝着正确方向迈出byteint一步,但是您还需要摆脱前面的所有这些。255&b[i]技巧实现了这一点。

这就是发生的情况255&b[i]
根据JLS &位运算符中定义的转换规则,首先将其操作数转换为 int,这意味着255&b[i]((int)255)&((int)b[i]). 当 byte 被转换为 int 时,它只会变得更宽:

10000100 = byte -124 ==> 11111111111111111111111110000100 = int -124

然后执行按位与。

11111111111111111111111110000100 = int -124 
&
00000000000000000000000011111111 = int 255
--------------------------------
00000000000000000000000010000100 = int 132

最终结果是int 132

于 2013-09-25T22:12:14.790 回答
3

它将有符号字节转换为整数,以便您获得(无符号)8 位的完整范围,而不是为超过 127 的值显示负数。

在 Java 中,由于字节是有符号的,因此一个字节的最大值是 127。所以假设数字是 128。在无符号字节中,这将表示为 10000000b。但是,对于 2 的补码负数,这将变为 -128。执行 255 & b[i] 将值强制为整数(32 位)并将高位清零,因此您得到 128 而不是 -128。

于 2013-09-25T21:07:11.897 回答
3

地址被写入为一组字节,从 0 到 255。Java 将每个字节解释为从 -128 到 127 的有符号字节。因此,将字节组成一个字符串作为有符号字节是没有意义的,例如-18.14.87.-45. 这与 IP 表示不匹配。

(int)255&b[i]

将其加宽b[i]一段int时间,从而忽略符号并将其读取为无符号。这(int)是轻浮的,因为255已经被解释为比 8 位更宽的东西。该0-255值在后面串联。因此,您会得到一个类似的 IP 192.168.1.200(请注意,此地址与之前给出的错误地址不匹配)。

作为一般的事情255&foo(或任何2^n-1整数 n,如 65536,或什至在十六进制中0xFF)是尝试安全地转换位长度。

于 2013-09-25T21:07:28.540 回答
0

ip 地址是合乎逻辑的,并带有子网掩码以查找 net_id 和 host_id。在示例中,它是相同的,但非常不寻常。子网掩码可用于分割出许多 net_id。在此处阅读示例:http ://www.garykessler.net/library/subnet_masks.html 。

于 2013-09-25T21:20:21.827 回答