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

Java源码学习之Integer类(二)——1.8新增的几个函数和变量

2016-03-22 17:49 483 查看
介绍一下新增的几个函数和变量,主要分析源码,用法请参考官方文档

1、几个跟无符号整数有关的函数

1.8中真的增加了很多个跟无符号有关的函数。。

1.1 public static String toUnsignedString(int i, int radix)

返回一个无符号的数字字符串表示,复用了Long的同名方法。具体实现等写到Long类的时候写。radix给定了进制

public static String toUnsignedString(int i),默认进制为十进制

1.2 public static int parseUnsignedInt(String s, int radix)

将给定字符串转换为无符号整型数,用参数radix给定基数(即进制)

public static int parseUnsignedInt(String s)默认进制为十进制

以下为parseUnsignedInt的源码以及相关注释、说明:

/**
* 前面很长一串的介绍就省略了哈。。。
* 字符串参数s只允许有‘+’和对应进制的数字。
*
* @throws     NumberFormatException if the {@code String}
*             does not contain a parsable {@code int}.
* 当这个字符串参数不存在可以被转换(映射)的整型数字,则抛出NumberFormatException异常
* @since 1.8
*/
public static int parseUnsignedInt(String s, int radix)
throws NumberFormatException {
if (s == null)  {
throw new NumberFormatException("null");
}

int len = s.length();
if (len > 0) {
char firstChar = s.charAt(0);
if (firstChar == '-') {
throw new
NumberFormatException(String.format("Illegal leading minus sign " +                                                      "on unsigned string %s.", s));
} else {
if (len <= 5 || // Integer.MAX_VALUE in Character.MAX_RADIX is 6 digits integer的最大值在支持的最大进制下占6位数字
(radix == 10 && len <= 9) ) { // Integer.MAX_VALUE in base 10 is 10 digits Integer的最大值在十进制下占10位数字
return parseInt(s, radix); //意思是未超过int有符号数所支持的范围,就可以用parseInt来算
} else {
long ell = Long.parseLong(s, radix);//若超过范围则用Long.parseLong方法来计算
if ((ell & 0xffff_ffff_0000_0000L) == 0) {//若未超过int无符号数支持的范围,即数字高八位为0,则返回int值
return (int) ell;
} else {//否则抛出异常,数字超过可表示的范围
throw new
NumberFormatException(String.format("String value %s exceeds " +                                                         "range of unsigned int.", s));
}
}
}
} else {
throw NumberFormatException.forInputString(s);
}
}


1.3 public static int compareUnsigned(int x, int y) 将两个参数看做无符号整数,比较大小。

以下为源码分析:

/**
* Compares two {@code int} values numerically treating the values
* as unsigned. 比较两个int值的大小(将这两个数看做无符号数)
*
* @param  x the first {@code int} to compare
* @param  y the second {@code int} to compare
* @return the value {@code 0} if {@code x == y}; a value less
*         than {@code 0} if {@code x < y} as unsigned values; and
*         a value greater than {@code 0} if {@code x > y} as
*         unsigned values
* 吐槽啊。。。这前面的说明写错了哇。。怎么三种情况返回的情况都一样。。
* 应该是: 当 x == y 时,返回0;当 x < y 时,返回-1;当 x > y 时,返回1
* 所以无符号对比大小,负数永远比非负数大。
* @since 1.8
*/
public static int compareUnsigned(int x, int y) {
//最小值是1000 0000 0000 0000 0000 0000 0000 0000 = -2^31
//在这个函数里,最大值是-1,因为在计算机中负数用补码存储,-1的补码为全1
return compare(x + MIN_VALUE, y + MIN_VALUE);
}


很明显地,可以分析得,由于负数的符号位为1,非负数的符号位为0,所以若将参数按照无符号数来比较大小的话,负数永远大于非负数,最大值始终为-1。而这个函数内部利用另一个函数compare来实现,compare比较的是有符号数,有符号数中,负数永远小于正数。这里将两个参数加上MIN_VALUE,即1000 0000 0000 0000 0000 0000 0000 0000,这样的话只改变数字的最高比特位(符号位),不影响后面的数值位。所以负数的最高位变成了0,正数的最高位变成了1,自然在compare函数里就分出大小来了。而非负数之间的比较并不受影响。

1.4 public static long toUnsignedLong(int x)将数值转换为无符号Long型。

/**
* Converts the argument to a {@code long} by an unsigned
* conversion.  In an unsigned conversion to a {@code long}, the
* high-order 32 bits of the {@code long} are zero and the
* low-order 32 bits are equal to the bits of the integer
* argument.
* 将参数转换为一个无符号的long类型的数值。在无符号数字的转换中,高32位均为0
* 低32位等于这个int型参数的比特位
* Consequently, zero and positive {@code int} values are mapped
* to a numerically equal {@code long} value and negative {@code
* int} values are mapped to a {@code long} value equal to the
* input plus 2<sup>32</sup>.
* 所以,非零值映射到一个相等的long类型的数值,而负数被映射到一个long类型的数值,其等于参数加上2的32次方
* 好像没有这样啊。。都一样啊。。数值都是一样的啊。。这是为啥呢。。而且下面实现的时候也并没有加上2的32次方呀
* 可能是在类型转换的时候加的2的32次方,但是最后与0xffffffffL相与了,高32位即使有1,也成0了
* @param  x the value to convert to an unsigned {@code long}
* @return the argument converted to {@code long} by an unsigned
*         conversion
* @since 1.8
*/
public static long toUnsignedLong(int x) {
// 确保高32位都是0,且低32位与原来的x值相同
return ((long) x) & 0xffffffffL;
}


原本以为这个函数很鸡肋,觉得无符号long跟longValue这个函数功能重叠呀,但是细想无符号数还是跟单纯的正数不同,无符号数是原本占有符号位的也被考虑为数值了,而且负数在计算机中以补码的形式存在,若是单纯转换为正数,那就是把这个二进制串改变转换成对应正数的补码了(正数原码、反码、补码相同),而无符号数是不改变这个二进制串,但是改变一下这个二进制串所代表的数字,变成了某个无符号非负数的原码了。

public static int divideUnsigned(int dividend, int divisor)

public static int remainderUnsigned(int dividend, int divisor)

这两个函数分别用来计算无符号int数的商和余数,核心就是利用toUnsignedLong函数转换为long型整数进行计算,再显示向下转型为int类型数据。。原因。。作者在注释中说

// In lieu of tricky code, for now just use long arithmetic.


就是说。。因为这个情况很棘手,所以现在暂时用long型数据~ ╮(╯_╰)╭

2、hashCode

Integer里的hashCode()直接返回的是value。hashCode的主要目的是为了帮助在集合中判断对象是否已经出现过。更详细的请参考下面的博文:

浅谈Java中的hashCode方法

3、表示int数值二进制补码形式字节数的变量

新增的变量BYTES:

public static final int BYTES = SIZE / Byte.SIZE;

4、Math有关的运算的函数

public static int sum(int a, int b)

public static int max(int a, int b)

public static int min(int a, int b)

这三个函数的函数名很明显,一看就知道函数的作用,就不说了~

为啥说它们跟Math有关嘞。。是因为它们的内部依次利用Math.sum、Math.max、Math.min来实现。。所以。。。为啥要在Integer里再写一遍相同作用的函数。。我是真的不懂。。。QAQ

预告!下篇写几个我觉得很妙的函数~

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: