Java源码学习之Integer类(二)——1.8新增的几个函数和变量
2016-03-22 17:49
483 查看
介绍一下新增的几个函数和变量,主要分析源码,用法请参考官方文档
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的源码以及相关注释、说明:
1.3 public static int compareUnsigned(int x, int y) 将两个参数看做无符号整数,比较大小。
以下为源码分析:
很明显地,可以分析得,由于负数的符号位为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型。
原本以为这个函数很鸡肋,觉得无符号long跟longValue这个函数功能重叠呀,但是细想无符号数还是跟单纯的正数不同,无符号数是原本占有符号位的也被考虑为数值了,而且负数在计算机中以补码的形式存在,若是单纯转换为正数,那就是把这个二进制串改变转换成对应正数的补码了(正数原码、反码、补码相同),而无符号数是不改变这个二进制串,但是改变一下这个二进制串所代表的数字,变成了某个无符号非负数的原码了。
public static int divideUnsigned(int dividend, int divisor)
public static int remainderUnsigned(int dividend, int divisor)
这两个函数分别用来计算无符号int数的商和余数,核心就是利用toUnsignedLong函数转换为long型整数进行计算,再显示向下转型为int类型数据。。原因。。作者在注释中说
就是说。。因为这个情况很棘手,所以现在暂时用long型数据~ ╮(╯_╰)╭
浅谈Java中的hashCode方法
public static final int BYTES = SIZE / Byte.SIZE;
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
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
预告!下篇写几个我觉得很妙的函数~
相关文章推荐
- Retrofit2和RxJava配合使用Demo
- IT十八掌作业_java基础第十五天_IO串行化/深度复制
- Dubbo java.io.IOException: Can not lock the registry cache file
- IT十八掌作业_java基础第十四天_IO
- Netbeans语言设置,颜色配置,自动完成 - 标签展开,Zen coding,英文界面
- hash表海量查找字符串(java版)
- Spring Bean的自动装配(Autowiring)
- 在eclipse中新建java项目缺少相关jar包的问题解决
- Java编程思想 感想
- java 高性能读模式(译)
- Java 判断文件夹、文件是否存在、否则创建文件夹
- java 为什么使用工厂方法设计模式
- javax.servlet.ServletException: Error instantiating servlet class Compiler 错误
- ImageMagick安装配置 for java项目 (使用jmagick)
- JAVA 对象引用,以及对象赋值
- java 解压zip包
- JVM加载类实例分析
- Eclipse设置server的编码
- java中成员访问修饰符,接口与抽象类相关知识
- Java中如何遍历Map对象的4种方法