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

本文详细介绍了Java 1.8中Integer类新增的与无符号整数相关的函数,如toUnsignedString、parseUnsignedInt、compareUnsigned,以及hashCode的实现和BYTES变量的含义。同时,还讨论了与Math相关的sum、max、min函数,并对Integer类中重复Math功能的函数提出疑问。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍一下新增的几个函数和变量,主要分析源码,用法请参考官方文档

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

预告!下篇写几个我觉得很妙的函数~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值