JDK源码分析 – Integer
Integer类的申明
public final class Integer extends Number implements Comparable<Integer> { … }
Integer用于对int类型数值的封装,并提供一些int类型数据操作的方法,Integer继承自Number类,Number是JDK的一个代表数值的超类,提供一些用于不同数值之间类型转换方法,常见的数值类型Double、Float等都继承自Number
Integer还实现了Comparable接口,主要用于Integer对象之间比较。
Integer字段、属性说明
Integer是对int型数值的封装,int型,占4个字节(JDK中定义占4字节),每个字节8位因次是32位,再除去一个符号位,因此范围是-2^31~2^31-1
下面列举几个重要的字段解释一下:
/**
*代表Integer封装的int整形数值
*/
private final int value; /**
*限制Integer对象存放最小值 -2^31
*/
@Native public static final int MIN_VALUE = 0x80000000; /**
* //限制Integer对象存放最大值 2^31-1
*/
@Native public static final int MAX_VALUE = 0x7fffffff; /**
*表示int二进制补码形式的值的位数。
*/
@Native public static final int SIZE = 32; /**
* 用于以int二进制补码形式表示值的字节数32/8 = 4字节
*/
public static final int BYTES = SIZE / Byte.SIZE;
Integer 部分方法分析
Integer类内部提供了很多方法,用于数值转换等操作,下面仍然是列举几个经常用到的分析一下实现过程:
构造函数Integer(String s)
/**
* 构造函数,允许传入一个字符串,通过内部函数parseInt尝试将其转成10进制int型数值,默认转成10进制,如果传入的String无法转换成Int则跑出异常
*/
public Integer(String s) throws NumberFormatException {
this.value = parseInt(s, 10);
}
int parseInt(String s, int radix)方法:
将字符串参数解析为指定的几进制带符号整数,转换失败抛出异常,string参数:将要转换为数值的字符串,int参数:代表需要转换的是几进制数值
JDK源码注释中给出一些示例:
/**
* JDK源码注释中的示例:
* <p>Examples:
* <blockquote><pre>
* parseInt("0", 10) returns 0
* parseInt("473", 10) returns 473
* parseInt("+42", 10) returns 42
* parseInt("-0", 10) returns 0
* parseInt("-FF", 16) returns -255
* parseInt("1100110", 2) returns 102
* parseInt("2147483647", 10) returns 2147483647
* parseInt("-2147483648", 10) returns -2147483648
* parseInt("2147483648", 10) throws a NumberFormatException
* parseInt("99", 8) throws a NumberFormatException
* parseInt("Kona", 10) throws a NumberFormatException
* parseInt("Kona", 27) returns 411787
*/
public static int parseInt(String s, int radix)
throws NumberFormatException
{
/*
* WARNING: This method may be invoked early during VM initialization
* before IntegerCache is initialized. Care must be taken to not use
* the valueOf method.
*/ //字符串为空直接异常
if (s == null) {
throw new NumberFormatException("null");
} //判断radix合法性,Integer内部允许2进制-36进制之间转换
//为什么是36进制? 看个示例
// Integer.parseInt("A", 16) = 10
// Integer.parseInt("a", 16) =10
// 上面可以看出不区分大小写,是不是10个数字+26个母?
if (radix < Character.MIN_RADIX) {
throw new NumberFormatException("radix " + radix +
" less than Character.MIN_RADIX");
}
if (radix > Character.MAX_RADIX) {
throw new NumberFormatException("radix " + radix +
" greater than Character.MAX_RADIX");
} int result = 0; //返回结果
boolean negative = false; //符号,正数or负数
int i = 0, len = s.length();
int limit = -Integer.MAX_VALUE;
int multmin;
int digit; //字符串长度大于0
if (len > 0) {
char firstChar = s.charAt(0);
if (firstChar < '0') { // Possible leading "+" or "-" 判断第一个字符是不是符号为=位
if (firstChar == '-') {
negative = true; //确定是负数标志
limit = Integer.MIN_VALUE; //限制最小值
} else if (firstChar != '+')
throw NumberFormatException.forInputString(s); //符号位既不是+也不是-,抛异常 if (len == 1) // Cannot have lone "+" or "-"
throw NumberFormatException.forInputString(s); //长度是1,只有符号位,没有数值,抛异常
i++;
}
multmin = limit / radix;
//遍历字符转,从最高位开始,整个过程以负数计算,逐位乘以单位制,最后再修正符号位,以10进制数123为例。转换过程如下
// result = -1
// result = -1*10-2 = -12
// result = -12*10-3 = -123
while (i < len) {
// Accumulating negatively avoids surprises near MAX_VALUE
digit = Character.digit(s.charAt(i++),radix); //将字符转换为radix进制数值,比如Character.digit(‘c’,16) = 12
if (digit < 0) {
throw NumberFormatException.forInputString(s);
}
if (result < multmin) {
throw NumberFormatException.forInputString(s);
}
result *= radix; //乘以单位制
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}
result -= digit;
}
} else {
throw NumberFormatException.forInputString(s);
}
return negative ? result : -result; //修正符号位
}
其他parseInt相关方法也都是调用这个最基础的方法进行转换。
Integer valueOf(int i)方法
返回指定int值的Integer实例,如果Integer不需要新实例,可优先使用此方法,而不是构造函数,因为此方法会缓存经常请求的值的Integer实例。该方法将始终缓存-128至127(含)范围内的值,并可缓存此范围之外的其他值
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Valueof方法内部使用了IntegerCache,判断如果数值在[IntegerCache.low, IntegerCache.high]这个范围内,则从缓存中读取,否则调用构造函数创建一个Integer实例
private static class IntegerCache {
static final int low = -128; //最小值 -128
static final int high; //最大值
static final Integer cache[]; //静态代码块,在Integer类加载时就已经缓存好
static {
// high value may be configured by property
int h = 127; //最大值 127
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); //读取最大值配置参数
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127); //在配置参数和默认h中取最大值
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h; cache = new Integer[(high - low) + 1]; //初始化数组
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++); //缓存integer对象 // range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
} private IntegerCache() {}
}
Valueof()方法完成将int型转换成Integer对象,其实就是一个装箱操作,Integer类型也可以直接赋值一个int数值:Integer integer = 100 这其实就是通过调用valueof()方法完成的。
相对应的方法:int intValue() 获取Integer对象内部value值,其实就是完成一个拆箱操作
public int intValue() {
return value;
}
下面给出一组测试示例,通过对Integer对比分析一下Integer对象的装箱拆箱和IntegerCache缓存:
Integer integer0 = Integer.valueOf(1); //IntegerCache缓存中读取
Integer integer1 = new Integer(1); //创建新实例
Integer integer2 = new Integer(1); //创建新实例
System.out.println(integer1.equals(integer2)); //true Integer.equal内部实现并不是比较两个Integer对象的引用,而是比较Integer.value值是否相等
System.out.println(integer1==integer2); //false integer1和integer2是两个不同的对象,引用不一样 Integer integer3 = 1;
Integer integer4 = 1;
System.out.println(integer3 == integer4);//true,integer3和integer4都完成装箱,从IntegerCache中取出相同的实例 Integer integer8 = 128;
Integer integer9 = 128;
System.out.println(integer8 == integer9);//false,integer8和integer9都完成装箱,New Integer(128)==new Integer(128) System.out.println(integer3 == integer1);//false,integer3通过调用valueof做了装箱操作 实际相当于 Integer.valueOf(1)==integer1
System.out.println(integer3 == integer0);//true,integer3通过调用valueof做了装箱操作 实际相当于 Integer.valueOf(1)==integer0 ,都从IntegerCache缓存中读取 int integer5 = 1;
Integer integer6 = new Integer(1); System.out.println(integer5 == integer5);//true 当Integer对象和int比较时,Integer对象调用intValue完成自动拆箱,转换为int,相当于两个int型比较 Integer integer7 = 1;
System.out.println(integer7==integer5); //true integer7先装箱,比较时又做了拆箱操作
Integer和int的区别
Integer是对int型封装后的类,int是java的一种基本数据类型(byte,char,short,int,long,float,double,boolean)
Integer是对象的引用,默认值为null,实例化后是一个对象的引用,指向存放该对象的地址,int作为基本数据类型,默认值为0
JDK源码分析 – Integer的更多相关文章
- JDK源码分析-Integer
Integer是平时开发中最常用的类之一,但是如果没有研究过源码很多特性和坑可能就不知道,下面深入源码来分析一下Integer的设计和实现. Integer: 继承结构: -java.lang.Obj ...
- JDK源码分析—— ArrayBlockingQueue 和 LinkedBlockingQueue
JDK源码分析—— ArrayBlockingQueue 和 LinkedBlockingQueue 目的:本文通过分析JDK源码来对比ArrayBlockingQueue 和LinkedBlocki ...
- JDK 源码分析(4)—— HashMap/LinkedHashMap/Hashtable
JDK 源码分析(4)-- HashMap/LinkedHashMap/Hashtable HashMap HashMap采用的是哈希算法+链表冲突解决,table的大小永远为2次幂,因为在初始化的时 ...
- 【JDK】JDK源码分析-HashMap(1)
概述 HashMap 是 Java 开发中最常用的容器类之一,也是面试的常客.它其实就是前文「数据结构与算法笔记(二)」中「散列表」的实现,处理散列冲突用的是“链表法”,并且在 JDK 1.8 做了优 ...
- 【JDK】JDK源码分析-Vector
概述 上文「JDK源码分析-ArrayList」主要分析了 ArrayList 的实现原理.本文分析 List 接口的另一个实现类:Vector. Vector 的内部实现与 ArrayList 类似 ...
- 【JDK】JDK源码分析-ArrayList
概述 ArrayList 是 List 接口的一个实现类,也是 Java 中最常用的容器实现类之一,可以把它理解为「可变数组」. 我们知道,Java 中的数组初始化时需要指定长度,而且指定后不能改变. ...
- 【JDK】JDK源码分析-CountDownLatch
概述 CountDownLatch 是并发包中的一个工具类,它的典型应用场景为:一个线程等待几个线程执行,待这几个线程结束后,该线程再继续执行. 简单起见,可以把它理解为一个倒数的计数器:初始值为线程 ...
- 【JDK】JDK源码分析-HashMap(2)
前文「JDK源码分析-HashMap(1)」分析了 HashMap 的内部结构和主要方法的实现原理.但是,面试中通常还会问到很多其他的问题,本文简要分析下常见的一些问题. 这里再贴一下 HashMap ...
- JDK源码分析(三)—— LinkedList
参考文档 JDK源码分析(4)之 LinkedList 相关
随机推荐
- C++练习--实现客户机(CLIENT)类
实现客户机(CLIENT)类. 定义字符型静态数据成员SeverName,保存其服务器名称: 整型静态数据成员ClientNum,记录已定义的客户数量: 定义静态函数ChangeSeverName() ...
- oracle 12.1.0.2中对象锁对系统的较大影响
环境:oracle 12.1.0.2 rac ,4节点 一.概述 通常来说,如果是oltp应用,那么部署在rac上,是不错的注意. 但实现情况中,往往是混合类型,既有OLTP也有OLAP. 如果没有 ...
- 快速玩转linux(4)
websever安装配置 Nginx & Apache 并发量. Apache基本操作 解释 命令 安装 yum install httpd 启动 service httpd start 停止 ...
- 【tp5.1】composer安装PHPExcel以及导入\导出Excel
一.安装PHPExcel 1.下载:PHPExcel https://github.com/PHPOffice/PHPExcel 2.解压后:Classes文件夹改名为PHPExcel 3.把文件夹 ...
- [转]不让iTunes备份到c盘
很多人现在的C盘都是空间不大的SSD硬盘,ITUNES备份老是占越来越大的空间,不如动手把它改成其它盘好了.下面7个步骤教你转移备份. 1.需要一个小工具:Juction.exe,如果你已经是WIN7 ...
- Python进阶-函数默认参数
Python进阶-函数默认参数 写在前面 如非特别说明,下文均基于Python3 一.默认参数 python为了简化函数的调用,提供了默认参数机制: def pow(x, n = 2): r = 1 ...
- python与mysql的连接过程
1.cmd---pip3 install PyMySQL2.>>>import pymysql3.mysql>create database bookdb character ...
- Java+Selenium3方法篇24-单选和多选按钮操作
Java+Selenium3方法篇24-单选和多选按钮操作 本篇介绍 webdriver处理前端单选按钮的操作.单选按钮一般叫raido button,就像我们在电子版的单选答题过程一样,单选只能点击 ...
- urllib,url中链接包含汉字怎么用百分号(%)加密处理
使用urllib中的quote,和unquote方法将汉字编码成gbk(2个百分号对应一个汉字)或者utf8(3个百分号对应一个汉字) 注意用%加密汉字时,汉字不能是Unicode编码格式,否则会报错 ...
- python基础之多线程
概念 进程:进程就是一个程序在一个数据集上的一次动态执行过程 程序:代码 数据集:程序执行过程中需要的资源 进程控制块:完成状态保存的单元 线程:线程是寄托在进程之上,为了提高系统的并发性 线程是进程 ...